深入了解Java 8中的可选类API
作為Java程序員,我們所有人都經(jīng)歷了以下情況:我們調(diào)用一個(gè)方法來(lái)獲取某個(gè)值,然后代替直接對(duì)返回值調(diào)用某些方法,我們首先必須檢查返回值不為null,然后在返回值。 這是像Guava這樣的外部API試圖解決的難題 。 此外,其他JVM語(yǔ)言(例如Scala,Ceylon等)也將這些功能嵌入了核心API。 在我以前的文章中,我寫了關(guān)于一種這樣的JVM語(yǔ)言即Scala的支持的文章 。
Java的較新版本(即Java 8)引入了一個(gè)名為Optional的新類。 可選類的Javadoc說:
可以包含或不包含非null值的容器對(duì)象。 如果存在值,則isPresent()將返回true,而get()將返回該值。
在這篇文章中,讓我們看一下Optional類中存在的每個(gè)方法,并用一個(gè)或兩個(gè)示例進(jìn)行解釋。
of
返回帶有指定的當(dāng)前非空值的Optional。
此方法是用于創(chuàng)建Optional類的實(shí)例的工廠方法。 這里要注意的一點(diǎn)是,傳遞給創(chuàng)建實(shí)例的值必須為非null。 如果傳遞的值為null,則拋出NullPointerException 。
//Creating an instance of Optional using the factory method. Optional<String> name = Optional.of("Sanaulla"); //This fails with a NullPointerException. Optional<String> someNull = Optional.of(null);ofNullable
返回描述指定值的Optional,如果非空,則返回空值。
與of方法類似,唯一的區(qū)別是此方法還處理空值。 一個(gè)例子:
//This represents an instance of Optional containing no value //i.e the value is 'null' Optional empty = Optional.ofNullable(null);isPresent
很簡(jiǎn)單的理解:
如果存在值,則返回true,否則返回false。
就像是:
//isPresent method is used to check if there is any //value embedded within the Optional instance. if (name.isPresent()) {//Invoking get method returns the value present//within the Optaional instance.System.out.println(name.get());//prints Sanaulla }get
如果此Optional中存在一個(gè)值,則返回該值,否則拋出NoSuchElementException。
此方法用于檢索Optional實(shí)例中存在的值。 我們?cè)谏厦婵吹搅艘粋€(gè)這樣的例子。 讓我們看一個(gè)拋出NoSuchElementException的例子:
//The below code prints: No value present try {//Invoking get method on an empty Optaional instance //throws NoSuchElementException.System.out.println(empty.get()); } catch (NoSuchElementException ex) {System.out.println(ex.getMessage()); }ifPresent
如果存在值,請(qǐng)使用該值調(diào)用指定的使用者,否則不執(zhí)行任何操作。
要了解此方法,您必須了解Consumer類 。 簡(jiǎn)而言之,Consumer是一個(gè)具有單個(gè)抽象方法的類,用于消費(fèi)一些值并對(duì)其執(zhí)行一些操作而不返回任何值。 在Java 8中,可以將lambda表達(dá)式傳遞給期望使用Consumer接口的方法。
如果Optional實(shí)例中存在該值,則上述方法接受代碼/ lambda表達(dá)式塊以執(zhí)行某些操作。 就像是:
orElse
返回值(如果存在),否則返回其他。
此方法要么返回Optional實(shí)例中存在的值,否則返回返回作為參數(shù)傳遞給orElse方法的值。 讓我們看一個(gè)例子:
//orElse method either returns the value present in the Optional instance //or returns the message passed to the method in case the value is null. //prints: There is no value present! System.out.println(empty.orElse("There is no value present!")); //prints: Sanaulla System.out.println(name.orElse("There is some value!"));orElseGet
該方法類似于上述方法。 區(qū)別在于如何獲取默認(rèn)值。 在orElse方法中,我們傳遞固定的字符串作為默認(rèn)值,但在orElseGet方法中,我們傳遞Supplier接口的實(shí)現(xiàn),該接口具有用于生成默認(rèn)值的方法。 讓我們看一個(gè)例子:
//orElseGet is similar to orElse with a difference that instead of passing //a default value, we pass in a lambda expression which generates the default //value for us. //prints: Default Value System.out.println(empty.orElseGet(() -> "Default Value")); //prints: Sanaulla System.out.println(name.orElseGet(() -> "Default Value"));orElseThrow
返回包含的值(如果存在),否則拋出異常,由提供的供應(yīng)商創(chuàng)建。
就像在方法orElseGet我們通過一個(gè)供應(yīng)商的接口 ,但在orElseThrow方法我們通過lambda表達(dá)式/方法引用拋出一個(gè)異常時(shí),未找到該值。 一個(gè)例子:
try {//orElseThrow similar to orElse method, instead of returning a default//value, this method throws an exception which is generated from //the lambda expression/method reference passed as a param to the method.empty.orElseThrow(ValueAbsentException::new); } catch (Throwable ex) {//prints: No value present in the Optional instanceSystem.out.println(ex.getMessage()); }而且ValueAbsentException的定義是:
class ValueAbsentException extends Throwable {public ValueAbsentException() {super();}public ValueAbsentException(String msg) {super(msg);}@Overridepublic String getMessage() {return "No value present in the Optional instance";} }map
從有關(guān)地圖方法的文檔中:
如果存在值,則將提供的映射函數(shù)應(yīng)用于該值,如果結(jié)果為非null,則返回描述結(jié)果的Optional。 否則,返回一個(gè)空的Optional。
此方法用于對(duì)Optional實(shí)例中存在的值應(yīng)用一組操作。 這組操作以表示函數(shù)接口實(shí)現(xiàn)的lambda表達(dá)式的形式傳遞。 如果您不熟悉Function接口,那么請(qǐng)花一些時(shí)間在這里閱讀我以前關(guān)于同一主題的博客文章。 讓我們看一下map方法的示例:
//map method modifies the value present within the Optional instance //by applying the lambda expression passed as a parameter. //The return value of the lambda expression is then wrapped into another //Optional instance. Optional<String> upperName = name.map((value) -> value.toUpperCase()); System.out.println(upperName.orElse("No value found"));flatMap
從flatMap方法的文檔中:
如果存在一個(gè)值,則對(duì)其應(yīng)用所提供的帶有可選參數(shù)的映射函數(shù),返回該結(jié)果,否則返回一個(gè)空的Optional。 此方法與map(Function)相似,但是提供的映射器是其結(jié)果已經(jīng)是Optional的映射器,如果調(diào)用它,則flatMap不會(huì)使用附加的Optional對(duì)其進(jìn)行包裝。
此方法與map方法非常相似,不同之處在于傳遞給它的映射函數(shù)的返回類型。 在map方法的情況下,映射函數(shù)的返回值可以是任何類型T ,而在flatMap方法的情況下,映射函數(shù)的返回值只能是Optional類型
讓我們看一下上面的示例,其中將map方法重寫為flatMap方法:
//flatMap is exactly similar to map function, the differece being in the //return type of the lambda expression passed to the method. //In the map method, the return type of the lambda expression can be anything //but the value is wrapped within an instance of Optional class before it //is returned from the map method, but in the flatMap method the return //type of lambda expression's is always an instance of Optional. upperName = name.flatMap((value) -> Optional.of(value.toUpperCase())); System.out.println(upperName.orElse("No value found"));//prints SANAULLAfilter
通過將要應(yīng)用于值的條件傳遞給filter方法,該方法用于將值限制在Optional實(shí)例內(nèi)。 該文件說:
如果存在一個(gè)值,并且該值與給定謂詞匹配,則返回描述該值的Optional,否則返回一個(gè)空的Optional。
到現(xiàn)在為止,您必須已經(jīng)知道如何將一些代碼塊傳遞給該方法。 是的,它是lambda表達(dá)式。 對(duì)于這種方法,我們必須傳遞一個(gè)lambda表達(dá)式,該表達(dá)式將是Predicate接口的實(shí)現(xiàn)。 如果您不熟悉謂詞界面,請(qǐng)花一些時(shí)間閱讀這篇文章。
現(xiàn)在讓我們看一下filter方法的不同用法,即滿足條件和不滿足條件的兩個(gè)示例。
//filter method is used to check if the given optional value satifies //some condtion. If it satifies the condition then the same Optional instance //is returned, otherwise an empty Optional instance is returned. Optional<String> longName = name.filter((value) -> value.length() > 6); System.out.println(longName.orElse("The name is less than 6 characters"));//prints Sanaulla//Another example where the value fails the condition passed to the //filter method. Optional<String> anotherName = Optional.of("Sana"); Optional<String> shortName = anotherName.filter((value) -> value.length() > 6); //prints: The name is less than 6 characters System.out.println(shortName.orElse("The name is less than 6 characters"));借此,我向您介紹了Optional類中存在的各種方法。 讓我將以上所有示例匯總為一個(gè)示例,如下所示:
public class OptionalDemo {public static void main(String[] args) {//Creating an instance of Optional//This value can also be returned from some method. Optional<String> name = Optional.of("Sanaulla");//This represents an instance of Optional containing no value//i.e the value is 'null'Optional empty = Optional.ofNullable(null);//isPresent method is used to check if there is any //value embedded within the Optional instance.if (name.isPresent()) {//Invoking get method returns the value present//within the Optaional instance.System.out.println(name.get());}try {//Invoking get method on an empty Optaional instance //throws NoSuchElementException.System.out.println(empty.get());} catch (NoSuchElementException ex) {System.out.println(ex.getMessage());}//ifPresent method takes a lambda expression as a parameter.//The lambda expression can then consume the value if it is present//and perform some operation with it.name.ifPresent((value) -> {System.out.println("The length of the value is: " + value.length());});//orElse method either returns the value present in the Optional instance//or returns the message passed to the method in case the value is null.System.out.println(empty.orElse("There is no value present!"));System.out.println(name.orElse("There is some value!"));//orElseGet is similar to orElse with a difference that instead of passing //a default value, we pass in a lambda expression which generates the default //value for us.System.out.println(empty.orElseGet(() -> "Default Value"));System.out.println(name.orElseGet(() -> "Default Value"));try {//orElseThrow similar to orElse method, instead of returning a default//value, this method throws an exception which is genereated from //the lambda expression/method reference passed as a param to the method.empty.orElseThrow(ValueAbsentException::new);} catch (Throwable ex) {System.out.println(ex.getMessage());}//map method modifies the value present within the Optional instance//by applying the lambda expression passed as a parameter. //The return value of the lambda expression is then wrapped into another//Optional instance.Optional<String> upperName = name.map((value) -> value.toUpperCase());System.out.println(upperName.orElse("No value found"));//flatMap is exactly similar to map function, the differece being in the//return type of the lambda expression passed to the method.//In the map method, the return type of the lambda expression can be anything//but the value is wrapped within an instance of Optional class before it //is returned from the map method, but in the flatMap method the return //type of lambda expression's is always an instance of Optional.upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));System.out.println(upperName.orElse("No value found"));//filter method is used to check if the given optional value satifies//some condtion. If it satifies the condition then the same Optional instance//is returned, otherwise an empty Optional instance is returned.Optional<String> longName = name.filter((value) -> value.length() > 6);System.out.println(longName.orElse("The name is less than 6 characters"));//Another example where the value fails the condition passed to the //filter method.Optional<String> anotherName = Optional.of("Sana");Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);System.out.println(shortName.orElse("The name is less than 6 characters"));}}以及以上代碼的輸出:
Sanaulla No value present The length of the value is: 8 There is no value present! Sanaulla Default Value Sanaulla No value present in the Optional instance SANAULLA SANAULLA Sanaulla The name is less than 6 characters 參考:在Experiences Unlimited博客上,我們的JCG合作伙伴 Mohamed Sanaulla深入研究了Java 8中的Optional類API 。翻譯自: https://www.javacodegeeks.com/2013/09/deep-dive-into-optional-class-api-in-java-8.html
總結(jié)
以上是生活随笔為你收集整理的深入了解Java 8中的可选类API的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DDOs攻击(企业ddos攻击)
- 下一篇: 如何用正则表达式杀死Java