3 回答
TA贡献1883条经验 获得超3个赞
Java 9
Optional.stream 已添加到JDK 9.这使您可以执行以下操作,而无需任何帮助方法:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Optional::stream)
.findFirst();
Java 8
是的,这是API中的一个小漏洞,因为将Optional变为零或一个长度的流有点不方便。你可以这样做:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
.findFirst();
但是在flatMap中使用三元运算符有点麻烦,所以编写一个小辅助函数来执行此操作可能会更好:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
if (opt.isPresent())
return Stream.of(opt.get());
else
return Stream.empty();
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
在这里,我已经内联调用resolve()而不是单独的map()操作,但这是一个品味问题。
TA贡献2016条经验 获得超9个赞
你不能像你已经做的那样更简洁。
你声称自己不想.filter(Optional::isPresent) 和 .map(Optional::get)。
这已经通过@StuartMarks描述的方法解决了,但是结果你现在将它映射到一个Optional<T>,所以现在你需要使用.flatMap(this::streamopt)和a get()到底。
所以它仍然包含两个语句,现在您可以使用新方法获得异常!因为,如果每个可选项都是空的怎么办?然后findFirst()将返回一个空的可选项,你的get()意志将失败!
那么你有什么:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
是真正实现你想要什么是最好的办法,那就是你要的结果保存为一个T,而不是一个Optional<T>。
我冒昧地创建了一个CustomOptional<T>包装的类,Optional<T>并提供了一个额外的方法,flatStream()。请注意,您无法扩展Optional<T>:
class CustomOptional<T> {
private final Optional<T> optional;
private CustomOptional() {
this.optional = Optional.empty();
}
private CustomOptional(final T value) {
this.optional = Optional.of(value);
}
private CustomOptional(final Optional<T> optional) {
this.optional = optional;
}
public Optional<T> getOptional() {
return optional;
}
public static <T> CustomOptional<T> empty() {
return new CustomOptional<>();
}
public static <T> CustomOptional<T> of(final T value) {
return new CustomOptional<>(value);
}
public static <T> CustomOptional<T> ofNullable(final T value) {
return (value == null) ? empty() : of(value);
}
public T get() {
return optional.get();
}
public boolean isPresent() {
return optional.isPresent();
}
public void ifPresent(final Consumer<? super T> consumer) {
optional.ifPresent(consumer);
}
public CustomOptional<T> filter(final Predicate<? super T> predicate) {
return new CustomOptional<>(optional.filter(predicate));
}
public <U> CustomOptional<U> map(final Function<? super T, ? extends U> mapper) {
return new CustomOptional<>(optional.map(mapper));
}
public <U> CustomOptional<U> flatMap(final Function<? super T, ? extends CustomOptional<U>> mapper) {
return new CustomOptional<>(optional.flatMap(mapper.andThen(cu -> cu.getOptional())));
}
public T orElse(final T other) {
return optional.orElse(other);
}
public T orElseGet(final Supplier<? extends T> other) {
return optional.orElseGet(other);
}
public <X extends Throwable> T orElseThrow(final Supplier<? extends X> exceptionSuppier) throws X {
return optional.orElseThrow(exceptionSuppier);
}
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
@Override
public boolean equals(final Object obj) {
return optional.equals(obj);
}
@Override
public int hashCode() {
return optional.hashCode();
}
@Override
public String toString() {
return optional.toString();
}
}
你会看到我添加了flatStream(),如下所示:
public Stream<T> flatStream() {
if (!optional.isPresent()) {
return Stream.empty();
}
return Stream.of(get());
}
用作:
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.flatMap(CustomOptional::flatStream)
.findFirst()
.get();
你还需要返回Stream<T>这里,因为你不能返回T,因为如果!optional.isPresent(),那么T == null如果你声明它这样的,但那么你.flatMap(CustomOptional::flatStream)会尝试添加null到流,这是不可能的。
例如:
public T getTOrNull() {
if (!optional.isPresent()) {
return null;
}
return get();
}
用作:
String result = Stream.of("a", "b", "c", "de", "fg", "hij")
.map(this::resolve)
.map(CustomOptional::getTOrNull)
.findFirst()
.get();
现在将抛出一个NullPointerException内部流操作。
结论
您使用的方法实际上是最好的方法。
添加回答
举报