如何链接lambda与最内层范围内可用的所有可选值而不嵌套Optional
发布时间:2020-12-15 02:20:34 所属栏目:Java 来源:网络整理
导读:这是我的另一个问题的分支: How to chain Optional#ifPresent() in lambda without nesting? 但是,现在的问题是如何提供一个lambda解决方案,其中所有可选值都在最里面的范围内可用: B b = procA().flatMap(this::procB).orElseThrow(SomeException::new);/
这是我的另一个问题的分支:
How to chain Optional#ifPresent() in lambda without nesting?
但是,现在的问题是如何提供一个lambda解决方案,其中所有可选值都在最里面的范围内可用: B b = procA().flatMap(this::procB).orElseThrow(SomeException::new); // Value from procA() is not available. 我原来的代码是: void SomeMethod() { procA().ifPresent(a -> { procB(a).ifPresent(b -> { // Do something with a and b return; }); }); throw new SomeException(); } 我理解最内层范围内的回报是错误的.新的flatMap示例说明了正确的行为. 我使用ifPresent()而不是get()来避免潜在的运行时异常,我可能无法检查可选的isPresent()的值. 解决方法
我发现这个问题非常有趣,因为具有潜在空值返回的链式调用是一种常见的麻烦,而Optional可以大大缩短通常的空检查链.但问题在于功能流方法的本质隐藏了映射函数中的中间值.嵌套是一种让它们可用的方法,但是如果你已经意识到,如果调用链的长度增长,它也会变得烦人.
我想不出一个简单轻量级的解决方案,但如果项目的性质经常导致这些情况,这个util类可以帮助: public static class ChainedOptional<T> { private final List<Object> intermediates; private final Optional<T> delegate; private ChainedOptional(List<Object> previousValues,Optional<T> delegate) { this.intermediates = new ArrayList<>(previousValues); intermediates.add(delegate.orElse(null)); this.delegate = delegate; } public static <T> ChainedOptional<T> of(T value) { return of(Optional.ofNullable(value)); } public static <T> ChainedOptional<T> of(Optional<T> delegate) { return new ChainedOptional<>(new ArrayList<>(),delegate); } public <R> ChainedOptional<R> map(Function<T,R> mapper) { return new ChainedOptional<>(intermediates,delegate.map(mapper)); } public ChainedOptional<T> ifPresent(Consumer<T> consumer) { delegate.ifPresent(consumer); return this; } public ChainedOptional<T> ifPresent(BiConsumer<List<Object>,T> consumer) { delegate.ifPresent(value -> consumer.accept(intermediates,value)); return this; } public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { return delegate.orElseThrow(exceptionSupplier); } public <X extends Throwable> T orElseThrow(Function<List<Object>,X> exceptionSupplier) throws X { return orElseThrow(() -> exceptionSupplier.apply(intermediates)); } } 您可以通过包装Optional或普通值来使用它.然后,当您使用map方法链接方法调用时,它将在列表中存储当前值时提供新的ChainedOptional.最后(ifPresent或者ElseThrow),您不仅会获得最后一个值,还会获得所有中间值的列表.因为不知道将链接多少个调用,所以我找不到以类型安全的方式存储这些值的方法. 看这里的例子: ChainedOptional.of(1) .map(s -> s + 1) .map(s -> "hello world") .map(s -> (String) null) .map(String::length) .ifPresent((intermediates,result) -> { System.out.println(intermediates); System.out.println("Result: " + result); }) .orElseThrow(intermediates -> { System.err.println(intermediates); return new NoSuchElementException(); }); // [1,2,hello world,null,null] // Exception in thread "main" java.util.NoSuchElementException // at ... ChainedOptional.of(1) .map(s -> s + 1) .map(s -> "hello world") // .map(s -> (String) null) .map(String::length) .ifPresent((intermediates,11] // Result: 11 希望这可以帮助.如果你想出一个更好的解决方案,请告诉我. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- java – 在完整的GC期间是否清除了WeakHashMap?
- java – 创建新的实例类引用
- java对properties文件进行解析
- 异常: Call From * 9000 failed on connection exception:
- 如何使用java代码在谷歌搜索?
- 使用JAVA实现RabbitMQ的发送告警
- java – 何时使用JDBC调用Connections,Statements和ResultS
- java – 在我的应用程序中使用相同的意图选择器共享多条消息
- java – 如何使用注释在Spring 4中重新加载属性文件?
- 为什么JDK同时具有Math.random()和Random类?