乐字节Java8核心特性之Optional

大家好啊,上次小乐给大家介绍了Java8最最重要的一个特性——Stream流,点击可以回顾哦。 Optional<T>类(java.util.Optional)是一个容器类,代表一个值存在或不存在,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常。 1、Optinal对象构建&值获取方法 实例代码如下 Optional<String> optional = Optional.of("java8");// NullPointerException空指针异常 值不能为空optional = Optional.of(null);optional = Optional.ofNullable("java8");System.out.println(optional.get());System.out.println(optional.orElse("java"));System.out.println(optional.orElseGet(()-> "java"));System.out.println(optional.orElseThrow(()->new RuntimeException()));// 值可空 推荐使用optional = Optional.ofNullable(null);// 运行时抛出NoSuchElementException异常System.out.println(optional.get());System.out.println(optional.orElse("java"));System.out.println(optional.orElseGet(()-> "java"));System.out.println(optional.orElseThrow(()->new RuntimeException()));2、Optional 逻辑判断操作这里可以使用Optional提供的API相关方法来执行逻辑判断操作 . 3、用户记录查询-消除null判断以用户模块为例,UserService中提供queryUserById方法供客户端调用,如下: public User queryUserById(Integer userId){ return null;}客户端调用Java8以前逻辑代码为例避免null通常为如下形式 User user= userService.queryUserById(10);if(null != user){ System.out.println("匹配到该用户"); /** * 执行其他操作 */}else{ System.out.println("用户不存在");}使用Optional 形式如下: Optional<User> userOptional = Optional.ofNullable(user);// 使用isPresent 方法进行判断if(userOptional.isPresent()){ System.out.println("匹配到该用户"); /** * 执行其他操作 */}else{ System.out.println("用户不存在");}当然,既然使用了Optional了,对于if else 的代码通常也是可以给省略掉 如下(程序逻辑只关注非空的情况,使用ifPresent 进行if判断): // 使用ifPresent 执行if 判断操作 userOptional.ifPresent((u)->{ System.out.println("匹配到该用户"); /** * 执行其他操作 */ });使用map orElse方法同样也可以执行if else的逻辑判断 如下: ...

June 10, 2019 · 1 min · jiezi

【修炼内功】[Java8] 使用Optional的正确姿势及序列化问题

本文已收录【修炼内功】跃迁之路 Java8的Optional为解决'空'的问题带来了很多新思路,查看Optional源码,实现非常简单,逻辑也并不复杂。Stuart Marks在其一次演讲中花了约1个小时的时间来讲述如何正确的使用Optional (Optional - The Mother of All Bikesheds by Stuart Marks),也有人调侃道1 hour for Optional, you gotta be kidding me.使用Optional不难,但用好Optional并不容易 Stuart Marks在演讲中提到了Optional的基本作用 Optional is intended to provide a limited mechanism for library method return types where there is a clear need to represent "no result", and where using null for that is overwhelmingly likely to cause errors.在以往的编程模型中,对于“没有内容”,大多数情况需要使用null来表示,而null值总是被人忽略处理(判断),从而在使用过程中极易引起NPE异常 Optional的出现并不是为了替代null,而是用来表示一个不可变的容器,它可以包含一个非null的T引用,也可以什么都不包含(不包含不等于null),非空的包含被称作persent,而空则被称作absent 本质上讲Optional类似于异常检查,它迫使API用户去关注/处理Optional中是否包含内容,从而避免因为忽略null值检查而导致的一些潜在隐患 假设有一个函数用来根据ID查询学生信息public Student search(Long id),现在有一个需求,需要根据ID查询学生姓名 public String searchName(Long id) { Student student = search(id); return student.getName();}注意,search函数是可能返回null的,在这种情况下searchName很有可能会抛出NPE异常 ...

April 21, 2019 · 3 min · jiezi

Java8新特性之Optional

上一篇小乐带大家了解了Java8新特性之Stream,接下来将会继续述说Java新特性之OptionalOptional<T>类(java.util.Optional)是一个容器类,代表一个值存在或不存在,原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常。1、of为非null的值创建一个Optional,如果值为null,则会抛出NullPointerExceptionOptional<Integer> optional = Optional.of(13);System.out.println(optional)2、ofNullable为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。Optional<String> optional2 = Optional.ofNullable(null);System.out.println(optional2);optional2 = Optional.ofNullable(“aaa”);System.out.println(optional2);3、isPresent如果值存在返回true,否则返回false。Optional<String> optional2 = Optional.ofNullable(null);System.out.println(optional2);System.out.println(optional2.isPresent());optional2 = Optional.ofNullable(“aaa”);System.out.println(optional2);System.out.println(optional2.isPresent());4、get如果Optional有值则将其返回,否则抛出NoSuchElementException。optional2 = Optional.ofNullable(“aaa”);System.out.println(optional2);System.out.println(optional2.isPresent());System.out.println(optional2.get());5、ifPresent 如果Optional实例有值则为其调用consumer,否则不做处理 。隐士地其中进行了null判断。public static void main(String[] args) { String str1 = “hello”; String str2 = null; Optional<String> optional1 = Optional.ofNullable(str1); Optional<String> optional2 = Optional.ofNullable(str2); optional1.ifPresent(str->System.out.println(str.length())); optional2.ifPresent(str-> System.out.println(str.length()));}6、orElse如果有值则将其返回,否则返回指定的其它值。public static void main(String[] args) { String str1 = “hello”; String str2 = null; Optional<String> optional1 = Optional.ofNullable(str1); Optional<String> optional2 = Optional.ofNullable(str2); System.out.println(optional1.orElse(“默认字符串”)); System.out.println(optional2.orElse(“默认字符串”));}7、orElseGetorElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的一个值作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值public static void main(String[] args) { Integer i = 20; Optional<Integer> op = Optional.ofNullable(i); System.out.println(op.orElseGet(()->0)); System.out.println(Optional.ofNullable(null).orElseGet(()->0));}8、orElseThrow如果有值则将其返回,否则抛出supplier接口创建的异常。public static void main(String[] args) { // 自己指定异常 System.out.println((Optional.ofNullable(“a”).orElseThrow(()->new IndexOutOfBoundsException()))); System.out.println((Optional.ofNullable(null).orElseThrow(()->new IndexOutOfBoundsException())));}9、mapmap处理有值的情况,如果有值,则对其执行调用map参数中的函数得到返回值,否则返回空Optional。public static void main(String[] args) { List<String> list = new ArrayList<String>(){ { add(“aaa”); add(“bbb”); add(null); } }; list.stream().forEach(temp ->{ Optional<String> opt = Optional.ofNullable(temp); System.out.println(opt.map(n -> { return n.toUpperCase(); }).orElse(“Nothing”)); }); // 简写为如下形式 list.stream().forEach(temp->{ System.out.println(Optional.ofNullable(temp).map(n->n.toUpperCase()).orElse(“Nothing”)); });}10、flatMap如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。flatMap与map(Funtion)方法类似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。 可以将内容public static void main(String[] args) { Optional<String> opt1 = Optional.ofNullable(“aaa”); Optional<String> opt2 = Optional.ofNullable(null); System.out.println(opt1.flatMap(n->{ return Optional.ofNullable(n.toUpperCase()); }).orElse(“还会没有吗”)); System.out.println( opt2.flatMap(n->{ return Optional.ofNullable(n.toUpperCase()); }).orElse(“还会没有吗”));}11、filter如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。public static void main(String[] args) { Optional<String> opt1 = Optional.ofNullable(“aabbbbaa”); Optional<String> opt2 = Optional.ofNullable(null); System.out.println(opt1.filter(value->value.length()>6)); System.out.println(opt2.filter(value->value.length()>6));}好了,Java8新特性之Optional就介绍到这里了,接下去小乐将会继续带大家了解Java8新特性,请继续关注,转载请说明出处和作者。 ...

April 12, 2019 · 1 min · jiezi

【现代C++】可选在C++中的表达--std::optional<>

背景我们在很多编程场合下都需要用到“可选”的概念,比如可选的参数,可选的返回值等。但对这一方面,传统C/C++支持得略显不足。下面通过几个实例说明这一问题。二分查找在二分查找算法中,有可能我们要查找的值不在集合里,这时我们该怎么表示呢?二分算法在前面的文章中有提供,给出了Python和Haskell版本:#pythondef binary_search(list, item): low = 0 high = len(list)—1 while low <= high: mid = (low + high) guess = list[mid] if guess == item: return mid if guess > item: high = mid - 1 else: low = mid + 1 return None–Haskellimport qualified Data.Vector as VbinarySearch :: (Ord a)=> V.Vector a -> Int -> Int -> a -> Maybe IntbinarySearch vec low high e | low > high = Nothing | vec V.! mid > e = binarySearch vec (mid+1) high e | vec V.! mid < e = binarySearch vec low (mid-1) e | otherwise = Just mid where mid = low + ((high-low) div 2)可以看出,Python使用了None表示值找不到,Haskell使用Nothing表示元素找不到,都没使用一些特定的数字来表示找不到的错误;两者大同小异,都表示函数返回值是"可选"的,即返回结果可能失败。最直观的好处是:使用类型表示这种情况可以给调用者更多显式的返回结果的信息,函数可读性更高。而在传统的C/C++里是没有相应支持的,我们只能:int binary_search(const std::vector<int> &list, int item) { size_t low{0}; size_t high{list.size() - 1}; while (low <= high) { auto mid = (low + high); auto guess = list[mid]; if (guess == item) { return mid; } else if (guess > item) { high = mid - 1; } else { low = mid + 1; } } return -1;}在这里我们使用特定值-1表示item没有找到。字符串查找函数同样,作为函数参数,我们在某些情况下也有参数可选的需求。如果我们调用函数时,若不指定该参数,会使用参数的默认值填充该参数。在标准库中,很多函数使用了这一策略。比如:标准库std::string类中的成员函数:size_type find( const basic_string& str, size_type pos = 0 ) const noexcept;size_type find_last_of( const basic_string& str, size_type pos = npos ) const noexcept;一个正向查找,一个反向查找,pos参数默认取一个特定的值,在这里分别取0和std::string::npos。然而在函数类型中,参数的类型仍然是size_type,并没有给调用者提供多少有用的信息。在其他语言中,这方面做的要相对更好,比如Haskell中,我们仍然可以使用Maybe T类型作为函数的参数,一目了然就可以看出这个参数需要处理可选情况。下面我们讨论传统方式都有哪些缺点。传统方式的缺点从以上两个应用实例可看出,传统方式实际上就是通过特定的值表示“可选”的概念。这种方式有什么缺点呢?从数据类型无法看出可选语义输入参数通过默认参数机制实现,相对来说还能看出点信息;但返回值可选的情况,我们完全从函数签名里看不出来一点信息,只能通过API文档得知。可选惯例不统一,规格多样按照惯例,通过找不到的情况,都会使用-1、nullptr等无意义的值;但惯例对编译器是没有约束力的,只能人为遵守,所以很有可能某些函数没有按照惯例来,最后导致的:不同的库惯例不一致,甚至同一个库不同人写的函数使用的惯例也不一致,千差万别,会提高使用的成本。当然,标准库是比较统一的,但这只是暂时掩盖了问题,而没有根除问题发生的原因。输入参数取值更加不统一,有些人喜欢使用有效的参数值作为默认参数,像find函数那样;有些人喜欢使用无效值作为默认参数,像find_last_of一样。使用有效值的优点是有助于理解,但某些情况下无法使用有效值,比如find_last_of的情况,因为字符串的大小是没法静态知道的。使用无效值避免了有效值的问题,但引发其他问题:偏函数的时候可以找到无效值,但全函数对于所有的参数都是有效的,这怎么找?所以,由于以上缺点,C++终于在C++17引入了std::optional<>工具。std::optional<>该工具相对容易使用,需要引入头文件#include <optional>。下面分三块说明其使用方式:函数参数可选假设要改造标准库的find函数,我们只需将签名修改为:size_type find( const basic_string& str, std::optional<size_type> pos = std::nullopt) const noexcept可以看到,pos已经成为可选类型optional<size_type>,同时我们使用std::nullopt常量作为其默认值。std::nullopt是标准库定义的特殊常量,用来表示pos参数没有被赋值过。即使参数换了类型,对函数的调用方式没有任何影响。我们仍然可以这么调用:std::string line {“abcd123445555”};line.find(“add”); //使用默认值line.find(“add”, 1); //从第二个字符开始函数返回值可选参照参数类型的改动,依葫芦画瓢地修改binary_search为:std::optional<int> binary_search(const std::vector<int> &list, int item) { size_t low{0}; size_t high{list.size() - 1}; while (low <= high) { auto mid = (low + high); auto guess = list[mid]; if (guess == item) { return mid; } else if (guess > item) { high = mid - 1; } else { low = mid + 1; } } return std::nullopt;}跟参数赋值一样,由于std::optional<T>提供了类型T到std::optional<T>的赋值转换,我们可以直接返回T类型的值。处理std::optional<T>类型的参数或返回值处理可选参数和可选返回值的操作是一样的,我们以处理可选返回值为例说明。…auto found = binary_search(list, 2);////因为标准库提供了到bool的默认类型转换,可以直接使用if判断if (found) { std::cout << “found " << found ; //可使用found取值}//我们也可以这样使用has_value()成员函数if (found.has_value()) { std::cout << “found " << found->value(); //使用成员函数value取值}//因为<optional>已经对操作符重载,我们还可以使用.if (found != std::nullopt) { std::cout << “found " << (*found).value(); }如果我们不判断found是否包含有效值而直接使用,此时可能会抛出std::bad_optional_access异常,需要捕捉;try { int n = found.value();} catch(const std::bad_optional_access& e) { std::cout << e.what() << ‘\n’;}捕捉异常会让执行流程中断,如果我们取到无效值的时候按0处理,可以:int n = found.value_or(0);这样能让流程更平滑地执行下去。代码示例以上就是该工具主要的用法,我们用一个例子结束该篇文章。模拟用户登录场景:用户使用登录名获取用户ID,从而完成登录。我们简单模拟了这个过程,定义了两个函数,get_user_from_login_name和write_login_log,函数比较简单,就不解释了。这里简化了登录场景,只要用户登录名在系统内存在就算登录成功。#include<iostream>#include <vector>#include <optional>#include <map>void write_login_log(int user_id, std::optional<time_t> cur_time = std::nullopt) { time_t cur = 0; if (cur_time) { cur = *cur_time; } else { cur = time(nullptr); } std::cout << “User: " << user_id << “, time: " << cur << std::endl;}std::optional<int> get_user_from_login_name(const std::string &login_name) { std::map<std::string, int> map_login{{“login1”, 1}, {“login2”, 2}}; auto found = map_login.find(login_name); if (found != map_login.cend()) { return found->second; } return std::nullopt;}int main() { auto user = get_user_from_login_name(“login1”); if (user) { write_login_log(*user); } return 0;}请继续关注我的公众号文章 ...

April 6, 2019 · 2 min · jiezi

深入理解 lambda表达式 与 Optional Null 源码解析(Java11 三)

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 ...

February 1, 2019 · 5 min · jiezi