新的Java 8流框架和朋友们制作了一些非常简洁的Java代码,但是我遇到了一个看似简单的情况,简单易懂.
考虑一个List<Thing> things方法Optional<Other> resolve(Thing thing).我想将Things 映射到Optional<Other>s并获得第一个Other.显而易见的解决方案是使用things.stream().flatMap(this::resolve).findFirst(),但flatMap要求您返回一个流,并且Optional没有stream()方法(或者它是Collection一个方法或提供将其转换为或以其方式查看的方法Collection).
我能想到的最好的是:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
Run Code Online (Sandbox Code Playgroud)
但这似乎是一个非常普遍的案例,似乎非常冗长.谁有更好的主意?
在Java中,Optional是作为public final class Optional<T> { ... }和不作为的密封层次Some和None.
为什么这不是这种情况?这是sealedJava 缺席的解决方法吗?背后有更深层次的推理吗?
如果您看一下方法实现,您会看到通过这种方式它具有丑陋的空检查:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
它们不仅丑陋,而且如果你有一个更长的方法链,isPresent则需要在每次调用时进行评估,即使Optional从一开始就是空的.
如果我们可以通过链中传递固定的实现,则可以避免.
optional
.map(i -> i) // isPresent()
.map(Object::toString) // isPresent()
.map(String::length) // isPresent()
.map(...) // isPresent()
Run Code Online (Sandbox Code Playgroud)
为什么没有用于模拟空和非空案例的子类型?
我并没有特别问为什么 Optional是最终的,而是为什么它没有实现,Some和None许多其他语言一样,所以为什么可选的声明为最终类并不是真的有用.