java8-Optional API

Doto丶發表於2018-03-17

眾所周知,在java語言開發中,NullPointerException是一直被大家所深惡痛絕的。然而在以前的java版本中,對空值的判斷有繁瑣而無趣。且十分影響程式碼的美觀。例如下面這種情況:

	    User user = ......;
	    
	    if (user != null){
	      String name = user.getName();
	      if (name != null){
	        log.debug(name);
	      }
	      log.debug("the name is not exist!");
	    }else {
	      log.debug("the user is not exist!");
		}
複製程式碼

這種程式碼真的是,,,,,,腦殼疼。
然而在java 8 中,這種情況得以改善了!那就是引入了Optional類。

Optional實際上是個容器:它可以儲存型別T的值,或者僅僅儲存null。Optional提供很多有用的方法,這樣我們就不用顯式進行空值檢測。

所幸OPtional 類的原始碼加上註釋不過三百多行,我就將其中的方法一一道來。

構造方法

Optional的構造方法有三種,Optional.of(),Optional.ofNullable(),Optional.empty()。 **Optional.of(T)** 這種構造方式要求栓如的值不能為空,否則直接回丟擲NullPointException。 **Optional.ofNullable(T)** 這種構造方式可以接受空值,當引數為空值時呼叫Optional.empty()構造一個空的Optional物件。 **Optional.empty()** 字面意思。

其他方法

**isPresent()** 返回boolean,表示Optional的值是否為空。 強烈不見使用此方法,因為它的作用和
return user != null
複製程式碼

一毛一樣,甚至我覺得他還沒有後者通俗易懂。。
get()
取到Optional內部的value,即構造時傳入的物件。 不建議。。。接下來的就是重點了!

ifPresent(Consumer<? super T> consumer)
通俗點講,這個方法的作用是:存在則對它做點什麼。
栗子:

 	Optional<User> userOpt = Optional.of(user);
    userOpt.ifPresent(System.out::println);
    
    // no elegant method!
    if (userOpt.isPresent()){
      System.out.println(userOpt.get());
    }
複製程式碼

幾個orElse

**orElse(T)** 作用:存在則返回,為空則返回預設值。
userOpt.orElse(new User());
複製程式碼

userOpt不為空時則返回他的值,為空值返回一個預設值,即新的User物件。

orElseGet(Supplier<? extends T> other) 作用:存在則返回,不存在則返回一個有函式產生的物件。

	userOpt.orElseGet(()-> make());

  	User make(){
    	return  new User("huyanshi",18,"china");

  	}
複製程式碼

這裡的make()方法很沒有必要,,,,可以直接由orElse()來設定預設值的,但是我偷懶了。。

orElseThrow(Supplier<? extends X> exceptionSupplier) 作用:存在則返回,不存在則丟擲異常,具體拋啥異常可以自己定義。

userOpt.orElseThrow(MyException::new);
複製程式碼

map

**map(map(Function mapper))** 如果有值,則對其執行呼叫mapping函式得到返回值。如果返回值不為null,則建立包含mapping返回值的Optional作為map方法返回值,否則返回空Optional。 map方法用來對Optional例項的值執行一系列操作。通過一組實現了Function介面的lambda表示式傳入操作。
//map方法執行傳入的lambda表示式引數對Optional例項的值進行修改。  
//為Lambda表示式的返回值建立新的Optional例項作為map方法的返回值。  
Optional<String> upperName = myValue.map((value) -> value.toUpperCase());  
System.out.println(upperName.orElse("No value found"));
複製程式碼

flatMap(Function<? super T,Optional<U mapper)
如果有值,為其執行mapping函式返回Optional型別返回值,否則返回空Optional。flatMap與map(Funtion)方法類似,區別在於flatMap中的mapper返回值必須是Optional。呼叫結束時,flatMap不會對結果用Optional封裝。
flatMap方法與map方法類似,區別在於mapping函式的返回值不同。map方法的mapping函式返回值可以是任何型別T,而flatMap方法的mapping函式必須是Optional。

//map方法中的lambda表示式返回值可以是任意型別,在map函式返回之前會包裝為Optional。   
//但flatMap方法中的lambda表示式返回值必須是Optionl例項。   
upperName = myValue.flatMap((value) -> Optional.of(value.toUpperCase()));  
System.out.println(upperName.orElse("No value found")); 
複製程式碼

map和flatmap使用方法類似,區別僅在於mapper方法的返回值型別不同,flatmap方法不會發展返回值再使用Optional進行封裝,因此傳入的方法必須返回Optional型別。
filter
如果有值並且滿足斷言條件返回包含該值的Optional,否則返回空Optional。
filter個方法通過傳入限定條件對Optional例項的值進行過濾。
對於filter函式我們可以傳入實現了Predicate介面的lambda表示式。

userOpt.filter(user1 -> user1.getName().length() > 6);
複製程式碼

如果user的名字長度大於6則返回自身,小於6則返回一個空值。

完。



ChangeLog

2018-03-09 完成

以上皆為個人所思所得,如有錯誤歡迎評論區指正。

歡迎轉載,煩請署名並保留原文連結。

更多學習筆記見個人部落格------>呼延十

相關文章