Say you've got a stream of @IBOutlet var text: UITextField! {
didSet {
text.delegate = self
}
}
, that you want to fire a Optional<T>
on (if present).
What's the most elegant way of handling this?
I can manage by filtering by Consumer<T>
and mapping by Optional::isPresent
, but that seems "hacky" and not in the spirit of Optional::isGet
:
Optional
答案 0 :(得分:4)
我同意这很麻烦,但它可能是最简单的解决方案而不会变得更加苛刻。
我在类似情况下做的一件事是创建一种方法将Optional
变成Stream
:
private Stream<T> optionalStream(Optional<T> optional) {
if (optional.isPresent())
return Stream.of(optional.get());
else
return Stream.empty());
}
然后您可以使用flatMap
:
Stream.of(a, b, c, d)
.flatMap(this::optionalStream).findFirst()...
当我第一次看到Optional
时,我想知道为什么他们没有包含stream
方法来执行此操作。更新:Java 9将包含Optional
的这种方法。
但说实话,我不确定这比filter
然后map
解决方案简单得多。
答案 1 :(得分:0)
我不确定下面的方法是否比你的更好......
首先,您可以尝试使用reduce()
:
Stream.of(a, b, c, d).reduce(Optional.empty(), (o1, o2) -> o1.isPresent() ? o1 : o2)
.ifPresent(s -> System.out.println("This seems cumbersome as well: " + s));
你仍然在查询Optional
,虽然这会在减少流时发生。
更优雅的方法(尽管不是那么冗长)是使用专门的Consumer
,只有当非空时才会接受Optional
的值。为此,您需要按如下方式定义OptionalConsumer
:
@FunctionalInterface
interface OptionalConsumer<T>
extends Consumer<Optional<T>> {
@Override
default void accept(Optional<T> o) {
if (o.isPresent()) {
this.acceptIfPresent(o.get());
}
}
void acceptIfPresent(T o);
static <U> OptionalConsumer<U> of(Consumer<U> c) {
return c::accept;
}
}
你可以这样使用它:
Stream.of(a, b, c, d).forEach(OptionalConsumer.of(s -> System.out.println("Better? " + s)));
注意:
OptionalConsumer
实际上是Consumer
,我不知道如何将其与findFirst()
一起使用。答案 2 :(得分:0)
我认为flatMap在这里真的很方便
Stream.of(a, b, c, d)
.flatMap(opt -> opt.map(Stream::of).orElse(Stream.empty()))
.findFirst()
.ifPresent(s -> System.out.println("This was cumbersome: " + s));
不理想,但至少要简洁。