博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Optional类型
阅读量:2444 次
发布时间:2019-05-10

本文共 4723 字,大约阅读时间需要 15 分钟。

Optional类型

optional<T>对象是一种包装器对象,要么包装了类型T对象,要么没有包装任何对象。对于第一种情况,称这种值为存在的。Optional<T>类型被当做一种更安全的方式,用来替代类型T的引用,这种引用要么引用某个对象,要么为null。但是,它只有在正确使用的情况下才会更安全。

使用Optional值

有效地使用Optional的关键是要使用这样的方法:它在值不存在的情况下会产生一个可替代物品,而只有在值存在的情况下才会使用这个值。

通常,在没有任何匹配时,我们会希望使用某种默认值,可能是空字符串:

String result = optionalString.orElse("");//The wrapped string, or "" if none

你还可以调用代码来计算默认值:

String result = optionlString.orElseGet(() -> Locale.getDefault().getDisplayName());//The function is only called when needed

或者可以在没有任何值时抛出异常:

String result = optionalString.orElseThrow(IllegalAccessException::new);

另一种使用可选值的策略是只有在其存在的情况下才消费该值。

ifPresent方法会接受一个函数。如果该可选值存在,那么它会被传递给该函数。否则,不会发生任何事情:

optionalString.ifPresent(v -> Process v);

如果在该值存在的情况下想要将其添加到某个集中,那么就可以调用:

optionalString.ifPresent(v -> results.add(v));

或者直接调用:

optionalString.ifPresent(results::add);

当调用ifPresent时,从该函数不会返回任何值。如果想要处理函数的结果,应该使用map:

Optional
added = optionalString.map(results::add);
方法 说明
T orElse(T other) 产生这个Optional的值,或者在该Optional为空时,产生other
T orElseGet(Supplier<? extends T> other) 产生这个Optional的值,或者在该Optional为空时,调用other的结果
<X extends Throwabled> T orElseThrow(Supplier<? extends X> exceptionSupplier) 产生这个Optional的值,或者在该Optional为空时,抛出调用exceptionSupplier的结果
void ifPresent(Consumer<? super T> consumer) 如果该Optional不为空,那么就将它的值传递给consumer
<U> Optional<U> map(Function<? super T, ? extends U> mapper) 产生将该Optional的值传递给mapper后的结果,只要这个Optional不为空且结果不为null,否则产生一个空Optional。

不适合使用Optional值的方式

get方法会在Optional值存在的情况下获得其中包装的元素,或者在不存在的情况下抛出一个NoSuchElementException对象。因此:

Optional
optionalValue = ...;optionalValue.get().someMethod();//并不比下面的方式更安全T value = ...;value.someMethod();

ifPresent方法会报告某个Optional<T>对象是否具有一个值,但是

if(optionalValue.isPresent())	optionalValue.get().someMethod();//并不比下面的方法更容易处理if(value != null)	value.someMethod();
方法 说明
T get() 产生这个Optional的值,或者在该Optional为空时,抛出一个NoSuchElementException
boolean isPresent() 如果该Optional不为空,则返回true

创建Optional值

Optional.of(result) 和 Optional.empty()

public static Optional
inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x); }

ofNullable方法被用啦作为可能出现的null值和可选值之间的桥梁:

Optional.ofNullable(obj)会在obj不为null的情况下返回Optional.of(obj),否则会返回Optional.empty()。

方法 说明
static <T> Optional<T> of(T value)
static <T> Optional<T> ofNullable(T value)
产生一个具有给定值的Optional。如果value为null,那么第一个方法抛出一个具有给定值的NullPointerExcepion对象,而第二个方法会产生一个空optional。
static <T> Optional<T> empty() 产生一个空Optional。

利用flatMap来构建Optional值的函数

假如有一个可以产生Optional对象的方法f、并且目标类型T具有一个可以产生Optional对象的方法g。如果他们都是普通的方法,那么你可以通过调用s.f().g()来将他们组合起来。但是这种组合没法工作,因为s.f()的类型为Optional<T>,而不是T。因此,需要调用:

Optional result = s.f().flatMap(T::G);

如果s.f()的值存在,那么g就可以应用到它上面。否则,就会返回一个空Optional

很明显,如果有更多的可以产生Optional值的方法或Lambda表达式,那么就可以重复此过程。你可以直接将flatMap的调用链接起来,从而构建由这些步骤构成的管道,只有所有步骤都成功时,该管段才会成功。

package pers.zhang;import java.util.*;/** * @Author: acton_zhang * @Date: 2020/3/25 11:49 上午 * @Version 1.0 */public class OptionalTest {
public static void main(String[] args) {
String[] strs = {
"one", "two", "three", "four", "five"}; List
wordList = Arrays.asList(strs); Optional
o = wordList.stream().filter(s -> s.contains("o")).findFirst(); System.out.println(o.orElse("No word contains o")); Optional
optionalString = Optional.empty(); String result = optionalString.orElse("N/A"); System.out.println("result:" + result); result = optionalString.orElseGet(() -> Locale.getDefault().getDisplayName()); System.out.println("result:" + result); try {
result = optionalString.orElseThrow(IllegalAccessException::new); System.out.println("result:" + result); } catch (IllegalAccessException e) {
e.printStackTrace(); } optionalString = wordList.stream().filter(s -> s.contains("e")).findFirst(); optionalString.ifPresent(s -> System.out.println(s + "contains e")); Set
results = new HashSet<>(); optionalString.ifPresent(results::add); Optional
added = optionalString.map(results::add); System.out.println(added); System.out.println(inverse(4.0).flatMap(OptionalTest::squareRoot)); System.out.println(inverse(-1.0).flatMap(OptionalTest::squareRoot)); System.out.println(inverse(0.0).flatMap(OptionalTest::squareRoot)); Optional
result2 = Optional.of(-4.0) .flatMap(OptionalTest::inverse) .flatMap(OptionalTest::squareRoot); System.out.println(result2); } public static Optional
inverse(Double x) { return x == 0 ? Optional.empty() : Optional.of(1 / x); } public static Optional
squareRoot(Double x) { return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x)); }}

转载地址:http://fvpqb.baihongyu.com/

你可能感兴趣的文章
RedHat上SSH2的安装和使用(转)
查看>>
安全使用RedHat Linux系统(转)
查看>>
RedHat Enterprise AS4硬盘安装步骤(转)
查看>>
Linux下多线程编程与信号处理易疏忽的一个例子(转)
查看>>
流氓和木马结合 强行关闭你的防火墙(转)
查看>>
SUSE一纸诉状控告SCO 捍卫知识产权(转)
查看>>
创建小于16M XFree86迷你Linux系统(转)
查看>>
shell中常用的工具(转)
查看>>
使用MySQL内建复制功能来最佳化可用性(转)
查看>>
一个比较vista的vista主题for rf5.0fb(转)
查看>>
Fedora Core 5.0 安装教程{下载}(转)
查看>>
把ACCESS的数据导入到Mysql中(转)
查看>>
shell里边子函数与主函数的实例(转)
查看>>
Linux中MAXIMA符号运算软件的简介(转)
查看>>
银行选择Linux 则无法回避高成本(转)
查看>>
上网聊天需要防范的几大威胁(转)
查看>>
[分享]后门清除完全篇(转)
查看>>
让你的Linux支持WEB修改密码(转)
查看>>
一个完整的ftp远程批量shell(转)
查看>>
crontab命令简介(转)
查看>>