import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author 陳楊 */ @RunWith(SpringRunner.class) @SpringBootTest public class OptionalTest { @Test public void testOptional() {
/* * A container object which may or may not contain a non-{@code null} value. * * 一個裝泛型爲T的 值容器 能夠包含Null 以規避 空指針異常 * public final class Optional<T> */
/* * Value-based Classes * * https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html * * final immutable (但裏面能夠包含指向 可變對象的引用) * 具備equals、hashCode和toString的實現 僅從實例的狀態計算 而不是從其標識或任何其餘對象或變量的狀態計算 * 不使用身份敏感的操做,例如實例之間的引用相等(==) 實例的hashCode,或實例的內部鎖(intrinsic lock)同步 * 判斷是否相等 僅比較equals()方法 而非對象的引用(==) * 沒有可訪問的構造函數 經過工廠方法實例化,不保證明例建立的一致性(不必定是單例) * * 基於值的對象 沒有public的構造方法 比較值是否相等(不比較引用) */
// private static final Optional<?> EMPTY = new Optional<>(); // private final T value; // Constructs an empty instance. // private Optional() { this.value = null; } /* * Constructs an instance with the described value. * * private Optional(T value) { this.value = Objects.requireNonNull(value); } */ /* * Returns an empty {@code Optional} instance. No value is present for this {@code Optional}. * * public static<T> Optional<T> empty() { * @SuppressWarnings("unchecked") * Optional<T> t = (Optional<T>) EMPTY; * return t; * } */ Optional<List<String>> empty = Optional.empty(); /* 構造一個容器裏不爲 null 的容器對象 * * public static <T> Optional<T> of(T value) { return new Optional<>(value); } */ Optional<List<String>> optional = Optional.of(Arrays.asList("Kirito", "Love", "Asuna")); /* 構造一個容器裏可能爲 null 的容器對象 * * public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); } */
/* 獲取容器中的全部值 * public T get() { * if (value == null) { * throw new NoSuchElementException("No value present"); * } * return value; * } */ System.out.println("---------------------------------------\n"); System.out.println("optional容器中存在的值:" + optional.get()); // 判斷 容器中存在值 返回true // public boolean isPresent() { return value != null; } System.out.println("---------------------------------------\n"); System.out.println("optional容器中存在值:" + optional.isPresent()); System.out.println("empty容器中存在值:" + empty.isPresent()); // 判斷 容器中不存在值 返回true // @since 11 // public boolean isEmpty() { return value == null; } System.out.println("---------------------------------------\n"); System.out.println("optional容器中不存在值:" + optional.isEmpty()); System.out.println("empty容器中不存在值:" + empty.isEmpty());
一、ifPresent(Consumer)html
/* * 若是存在 value 對 value 進行一個 Consumer消費 * public void ifPresent(Consumer<? super T> action) { * if (value != null) { * action.accept(value); * } * } * */ System.out.println("---------------------------------------\n"); System.out.println("optional容器中存在值就進行Consumer消費(打印輸出)"); optional.ifPresent(System.out::println);
二、ifPresentOrElse(Consumer)java
/* 若是存在 value 對 value 進行一個 Consumer消費 不存在 執行emptyAction(empty-based action) * @since 9 * public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) { * if (value != null) { * action.accept(value); * } else { * emptyAction.run(); * } * } */ System.out.println("---------------------------------------\n"); System.out.println("容器中存在值就打印值,不存在打印 hello world"); optional.ifPresentOrElse(System.out::println, () -> System.out.println("hello world")); empty.ifPresentOrElse(System.out::println, () -> System.out.println("hello world"));
三、filter(Predicate)spring
/* * 若是存在value 且符合預期predicate 則對 value 進行預期操做predicate.test(value) 不然返回empty * public Optional<T> filter(Predicate<? super T> predicate) { * Objects.requireNonNull(predicate); * if (!isPresent()) { * return this; * } else { * return predicate.test(value) ? this : empty(); * } * } */ System.out.println("---------------------------------------\n"); System.out.println("遍歷集合元素"); optional.filter(strings -> { strings.forEach(System.out::println); return true; });
四、or(Supplier)api
/* * 若是存在value 則返回value 不然使用supplier接口的get()方法 構造出一個Optional * @since 9 * public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier) { * Objects.requireNonNull(supplier); * if (isPresent()) { * return this; * } else { * @SuppressWarnings("unchecked") * Optional<T> r = (Optional<T>) supplier.get(); * return Objects.requireNonNull(r); * } * } */ System.out.println("---------------------------------------\n"); Supplier<Optional<List<String>>> sup = () -> Optional.ofNullable(Arrays.asList("Optional", "or", "supplier")); System.out.println(empty.or(sup));
五、Stream.of(value)oracle
/* * 若是存在value 則返回Stream.of(value) 不然返回一個Stream.empty() * @since 9 * public Stream<T> stream() { * if (!isPresent()) { * return Stream.empty(); * } else { * return Stream.of(value); * } * } */ System.out.println("---------------------------------------\n"); System.out.println("以stream流 遍歷optional容器內的值"); Stream<List<String>> stream = Stream.of(optional.get()); stream.forEach(System.out::println);
六、orElse(T other)app
/* * 若是存在value 則返回value 不然返回T other * public T orElse(T other) { * return value != null ? value : other; * } */ System.out.println("---------------------------------------\n"); System.out.println(" 容器中存在值就返回值 不存在就返回{\"hello\",\"world\"}"); System.out.println(empty.orElse(Arrays.asList("hello", "world")));
七、orElseGet(Supplier)函數
/* * 若是存在value 則返回value 不然返回Supplier接口實現 * public T orElseGet(Supplier<? extends T> supplier) { * return value != null ? value : supplier.get(); * } */ System.out.println("---------------------------------------\n"); Supplier<List<String>> listSupplier = () -> Arrays.asList("do", "orElseGet"); System.out.println(empty.orElseGet(listSupplier));
八、orElseThrow測試
/* * 若是存在value 則返回value 不然拋出異常NoSuchElementException * @since 10 * public T orElseThrow() { * if (value == null) { * throw new NoSuchElementException("No value present"); * } * return value; * } */ System.out.println("---------------------------------------\n"); System.out.println(" 容器中存在值就返回值 不存在就返回NoSuchElementException"); System.out.println(optional.orElseThrow()); try { System.out.println(empty.orElseThrow()); } catch (NoSuchElementException e) { System.out.println(" NoSuchElementException ---> No value present"); }
九、orElseThrow(Supplier)ui
/* * 若是存在value 則返回value 不然使用Supplier接口生成一個被拋出的exceptionSupplier -->exception * public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { * if (value != null) { * return value; * } else { * throw exceptionSupplier.get(); * } * } */ System.out.println("---------------------------------------\n"); Supplier<NoSuchElementException> noSuchElementException = NoSuchElementException::new; try { System.out.println(empty.orElseThrow(noSuchElementException)); } catch (NoSuchElementException e) { System.out.println(" Supplier NoSuchElementException ---> No value present"); }
十、map(Function)this
/* * * 若是存在value 則返回value並做爲mapper的輸入 將其輸出做爲新的value存放至Optional 不然返回一個null的Optional * 若是通過mapper 後獲得的結果爲null 返回一個null的Optional * mapper函數若爲null 則拋出NullPointerException * map:對集合中每一個元素進行操做 * * * 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)); * } * } */ System.out.println("---------------------------------------\n"); Function<List<String>, List<String>> function = up -> up.stream().map(String::toUpperCase).collect(Collectors.toList()); Optional<List<String>> o = optional.map(function); System.out.println(o.get());
十一、flatMap(Function)
/* * 若是存在value 則返回value並做爲mapper的輸入 將其輸出做爲新的value存放至Optional 不然返回一個null的Optional * 若是通過mapper 後獲得的結果爲null 返回一個null的Optional * mapper函數若爲null 則拋出NullPointerException * * 與map的方法的區別: * map * * return Optional.ofNullable(mapper.apply(value)); * * flatMap * * Optional<U> r = (Optional<U>) mapper.apply(value); * return Objects.requireNonNull(r); * flatMap:對集合中每一個元素進行操做而後再扁平化 * * * public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper) { * Objects.requireNonNull(mapper); * if (!isPresent()) { * return empty(); * } else { * @SuppressWarnings("unchecked") * Optional<U> r = (Optional<U>) mapper.apply(value); * return Objects.requireNonNull(r); * } * } */ System.out.println("---------------------------------------\n"); Function<List<String>, Optional<List<String>>> func = up -> Optional.of(up.stream().map(String::toUpperCase).collect(Collectors.toList())); Optional<List<String>> u = optional.flatMap(func); System.out.println(u.get()); } }
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.2.RELEASE) 2019-02-01 18:29:34.870 INFO 17140 --- [ main] com.java.design.java8.OptionalTest : Starting OptionalTest on DESKTOP-87RMBG4 with PID 17140 (started by 46250 in E:\IdeaProjects\design) 2019-02-01 18:29:34.871 INFO 17140 --- [ main] com.java.design.java8.OptionalTest : No active profile set, falling back to default profiles: default 2019-02-01 18:29:35.437 INFO 17140 --- [ main] com.java.design.java8.OptionalTest : Started OptionalTest in 0.775 seconds (JVM running for 1.574) --------------------------------------- optional容器中存在的值:[Kirito, Love, Asuna] --------------------------------------- optional容器中存在值:true empty容器中存在值:false --------------------------------------- optional容器中不存在值:false empty容器中不存在值:true --------------------------------------- optional容器中存在值就進行Consumer消費(打印輸出) [Kirito, Love, Asuna] --------------------------------------- 容器中存在值就打印值,不存在打印 hello world [Kirito, Love, Asuna] hello world --------------------------------------- 遍歷集合元素 Kirito Love Asuna --------------------------------------- Optional[[Optional, or, supplier]] --------------------------------------- 以stream流 遍歷optional容器內的值 [Kirito, Love, Asuna] --------------------------------------- 容器中存在值就返回值 不存在就返回{"hello","world"} [hello, world] --------------------------------------- [do, orElseGet] --------------------------------------- 容器中存在值就返回值 不存在就返回NoSuchElementException [Kirito, Love, Asuna] NoSuchElementException ---> No value present --------------------------------------- Supplier NoSuchElementException ---> No value present --------------------------------------- [KIRITO, LOVE, ASUNA] --------------------------------------- [KIRITO, LOVE, ASUNA] Process finished with exit code 0