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)@SpringBootTestpublic class OptionalTest { @Test public void testOptional() {一、Optional出现的缘由/ * A container object which may or may not contain a non-{@code null} value. * * 一个装泛型为T的 值容器 可以包含Null 以规避 空指针异常 * public final class Optional<T> /二、深入理解 Value-based Classes/ * 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的构造方法 比较值是否相等(不比较引用) /三、Optional容器的构造// 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());五、高级拓展1、ifPresent(Consumer)/ * 如果存在 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);2、ifPresentOrElse(Consumer)/ 如果存在 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”));3、filter(Predicate)/ * 如果存在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;});4、or(Supplier)/ * 如果存在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));5、Stream.of(value)/ * 如果存在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);6、orElse(T other)/ * 如果存在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”)));7、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));8、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");}9、orElseThrow(Supplier)/ * 如果存在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");}10、map(Function)/ * * 如果存在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());11、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: default2019-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容器中存在值:trueempty容器中存在值:false—————————————optional容器中不存在值:falseempty容器中不存在值:true—————————————optional容器中存在值就进行Consumer消费(打印输出)[Kirito, Love, Asuna]—————————————容器中存在值就打印值,不存在打印 hello world[Kirito, Love, Asuna]hello world—————————————遍历集合元素KiritoLoveAsuna—————————————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
...