聆聽 沉澱 傳播 … 關注微信公衆號【
Java之言
】,助你放棄編程之路!java
標題 | 文章連接 |
---|---|
玩轉 Java8 Stream,讓你代碼更高效緊湊簡潔 | juejin.cn/post/692113… |
官方定義:編程
public final class Optional<T> extends Object
微信A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.markdown
Additional methods that depend on the presence or absence of a contained value are provided, such as orElse() (return a default value if value not present) and ifPresent() (execute a block of code if the value is present).app
This is a value-based class; use of identity-sensitivemin operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided.ide
Optional
類,一個可包含或不包含非null值
的容器對象
。若是值存在,isPresent()
方法將返回 true 而且get()
返回該值。函數式編程這個類還提供了其餘方法,這些方法取決於它所包含值的存在與否,例如
orElse()
(若是不存在值,則返回默認值)和ifPresent()
(若是存在值,則執行代碼塊)。函數這是一個基於值的類,因此對於Optional實例的一些身份敏感操做(包括引用相等==,hashCode,同步)會產生沒法預料的結果,應該避免使用。post
- 既然 Optional 類裏面包含的值能夠爲
null
,不言而喻,那咱們就能夠不用顯式地進行空值檢測,即咱們能夠不用作判空操做,很好的解決了空指針異常問題(NullPointerException
)。- Java8引入了函數式編程,而 Optional 是其中必不可少的一部分,幫助在範式中實現。結合 Stream 能夠寫出簡潔高效的代碼。
先舉個栗子,輸出一個員工的崗位名稱,若是崗位名稱爲空,則輸出默認值 - 實習生:ui
if (null != staff.getPost().getName()) {
System.out.println(staff.getPost().getName());
} else {
System.out.println("實習生");
}
複製代碼
以上語句有可能拋出NPE,爲了健壯性,咱們須要寫判空:
if (null != staff) {
Post post = staff.getPost();
if (null != post) {
String name = post.getName();
if (null != name) {
System.out.println(name);
} else {
System.out.println("實習生");
}
}
}
複製代碼
可是寫了大量的判空操做,很繁瑣,代碼冗餘還很難維護。若是使用Optional則很簡單以下:
System.out.println(
Optional.ofNullable(staff).map(Staff::getPost).map(Post::getName).orElse("實習生"));
複製代碼
public final class Optional<T> {
// 包含一個空值的Optional容器對象
private static final Optional<?> EMPTY = new Optional<>();
// Optional容器包含的值
private final T value;
// 私有構造方法,建立一個包含空值的Optional容器對象
private Optional() {
this.value = null;
}
// 靜態方法,建立一個空值的Optional容器對象
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
// 私有構造方法,建立一個包含非空值的Optional容器對象
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
// 靜態方法,建立一個包含非空值的Optional容器對象
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
// 靜態方法,建立一個包含可空值的Optional容器對象
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
// 獲取值,若是值爲null,則拋出異常
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
// 判斷值是否不爲null
public boolean isPresent() {
return value != null;
}
// 若是值不爲null,則使用改值調用consumer函數
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
// 若是值存志,而且這個值匹配給定的 predicate,返回一個Optional用以描述這個值,不然返回一個空的Optional。
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
// 若是值存在,則對其執行調用映射函數獲得新的返回值。不然返回空Optional。
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
// 若是值存在,返回基於Optional包含的映射方法的值,不然返回一個空的Optional
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
// 若是值存在,返回此值, 不然返回other。
public T orElse(T other) {
return value != null ? value : other;
}
// 若是值存在,返回此值, 不然調用other函數,並返回other函數的結果。
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
// 若是值存在,返回此值,不然拋出由Supplier繼承的異常
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
}
複製代碼
// 建立一個空值的Optional對象
Optional<Object> emptyOptional = Optional.empty();
// 建立一個值可爲空的Optional對象
Optional<Staff> staffOptional = Optional.ofNullable(staff);
// 建立一個非空值的Optional對象
Optional<Staff> staffOptional1 = Optional.of(staff);
複製代碼
// 返回Optional容器對象中包含的值,若是值爲null則拋出異常
Staff staff = staffOptional.get();
複製代碼
// 判斷值是否存在
if (staffOptional.isPresent()) {
Staff staff = staffOptional.get();
}
複製代碼
// 若是值存在,則輸出值
staffOptional.ifPresent(System.out::println);
複製代碼
// 是否存在18歲的員工,若是存在,則輸出她的姓名
staffOptional.filter(staff -> staff.getAge() == 18)
.ifPresent(staff -> System.out.println(staff.getName()));
複製代碼
// 獲取員工的姓名,若是staff或name爲null,輸出'未知'
System.out.println(staffOptional.map(Staff::getName).orElse("未知"));
複製代碼
// 若是staff爲null,將新生成的Staff對象賦值給staff
staff = Optional.ofNullable(staff).orElse(new Staff());
複製代碼
// // 若是staff爲null,才new出一個Staff對象,賦值給staff,它與orElse不一樣的是執行時機不一樣,orElseGet是值爲空才調用other函數。
staff = Optional.ofNullable(staff).orElseGet(Staff::new);
複製代碼
// 若是staff爲null,則拋出異常
staff = Optional.ofNullable(staff).orElseThrow(() -> new NullPointerException());
複製代碼
// 找出一個員工大於等於18歲的員工
Optional<Staff> staffOptional = staffList.stream().filter(staff -> staff.getAge() >= 18).findFirst();
if (staffOptional.isPresent()) {
Staff staff = staffOptional2.get();
}
複製代碼