Java 如何在不嵌套optional#ifPresent()的情况下,将lambda与最内层作用域中可用的所有可选值链接起来?
这是我另一个问题的一个分支: 但是,现在的问题是如何提供一个lambda解决方案,其中所有可选值都在最内部的作用域中可用:Java 如何在不嵌套optional#ifPresent()的情况下,将lambda与最内层作用域中可用的所有可选值链接起来?,java,lambda,optional,Java,Lambda,Optional,这是我另一个问题的一个分支: 但是,现在的问题是如何提供一个lambda解决方案,其中所有可选值都在最内部的作用域中可用: B b = procA().flatMap(this::procB).orElseThrow(SomeException::new); // Value from procA() is not available. 我最初的代码是: void SomeMethod() { procA().ifPresent(a -> { procB(a).i
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()
的值,我发现这个问题非常有趣,因为带有潜在null
返回的链式调用是一个常见的麻烦,可选的可以大大缩短通常的空检查链。但问题是函数流方法的性质隐藏了映射函数中的中间值。嵌套是保持它们可用的一种方法,但正如您所意识到的,如果调用链的长度增加,它也会变得烦人
我想不出一个简单而轻量级的解决方案,但是如果项目的性质经常导致这些情况,那么这个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));
}
}
希望这有帮助。如果您有更好的解决方案,请告诉我。它们是可用的。你可以用a和b做点什么。问题是什么?
a
无法使用flatMap
方法。我希望避免嵌套ifPresent()
,因为a
和b
都可以在最内部的作用域中使用,并且如果任何嵌套失败,都可以抛出异常。这非常鼓舞人心,我做了一些改进,使其更加完整(现在针对Java 8)。可在以下网址找到:
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, result) -> {
System.out.println(intermediates);
System.out.println("Result: " + result);
})
.orElseThrow(intermediates -> {
System.err.println(intermediates);
return new NoSuchElementException();
});
// [1, 2, hello world, 11]
// Result: 11