你已经做得很简洁了,无法更加简洁。
你声称不想使用.filter(Optional::isPresent)
和.map(Optional::get)
。
这个问题已经被@StuartMarks描述的方法解决了,但是作为结果,现在你需要将其映射到一个Optional<T>
,所以现在你需要使用.flatMap(this::streamopt)
并最终使用get()
。
因此,它仍然由两个语句组成,并且新方法可能会出现异常!因为,如果每个可选项都为空怎么办?那么findFirst()
将返回一个空的可选项,而你的get()
将失败!
所以你现在有:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
is实际上是实现你想要的最佳方式,而这就是你想将结果保存为T
而不是Optional<T>
。
我冒昧创建了一个包装Optional<T>
并提供额外方法flatStream()
的CustomOptional<T>
类。请注意,您无法扩展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
。
结论
你使用的方法实际上是最好的方法。
.flatMap(Optional::toStream)
的版本更易读。使用你的版本,你可以看到正在发生什么。 - skiwiOptional.stream
方法了。 - Stuart MarksflatMap
,但这通常会引入合并操作,而一些简单的.filter().map()
则不会像合并操作那样具有良好的可扩展性。 - Crystark