你可以强迫reduce
去做这个。逻辑是减少false
,将值设置为true
如果遇到任何有用的数据。
的结果是reduce
那么就是false
那么没有遇到任何项目。如果遇到任何项目,那么结果将是true
:
boolean hasItems = stream.reduce(false, (o, i) -> {
itemConsumer.accept(i);
return true;
}, (l, r) -> l | r);
if (!hasItems) {
emptyAction.run();
}
这对于并行流来说应该可以正常工作,因为任何遇到项目的流都会将该值设置为true
.
然而,我不确定我是否喜欢这个,因为它的使用有点迟钝reduce
手术。
另一种选择是使用AtomicBoolean
作为一个可变的boolean
容器:
final AtomicBoolean hasItems = new AtomicBoolean(false);
stream.forEach(i -> {
itemConsumer.accept(i);
hasItems.set(true);
});
if (!hasItems.get()) {
emptyAction.run();
}
但我不知道我是否或多或少喜欢这样。
最后,你可以拥有你的itemConsumer
记住状态:
class ItemConsumer implements Consumer<Object> {
private volatile boolean hasConsumedAny;
@Override
public void accept(Object o) {
hasConsumedAny = true;
//magic magic
}
public boolean isHasConsumedAny() {
return hasConsumedAny;
}
}
final ItemConsumer itemConsumer = new ItemConsumer();
stream.forEach(itemConsumer::accept);
if (!itemConsumer.isHasConsumedAny()) {
emptyAction.run();
}
这看起来更简洁,但可能不实用。所以也许是一个装饰器模式 -
class ItemConsumer<T> implements Consumer<T> {
private volatile boolean hasConsumedAny;
private final Consumer<T> delegate;
ItemConsumer(final Consumer<T> delegate) {
this.delegate = delegate;
}
@Override
public void accept(T t) {
hasConsumedAny = true;
delegate.accept(t);
}
public boolean isHasConsumedAny() {
return hasConsumedAny;
}
}
final ItemConsumer<Object> consumer = new ItemConsumer<Object>(() -> /** magic **/);
TL;DR: 某物一定要记住你在消费过程中是否遇到过什么事情Stream
, be it:
- the
Stream
本身的情况下reduce
;
-
AtomicBoolean
; or
- 消费者
我认为从逻辑的角度来看,消费者可能处于最佳位置。