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() {
一、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: 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