如果您能够使用有限的并行能力,以下解决方案将会奏效:
private static Stream nonEmptyStream(
Stream stream, Supplier e) {
Spliterator it=stream.spliterator();
return StreamSupport.stream(new Spliterator() {
boolean seen;
public boolean tryAdvance(Consumer super T> action) {
boolean r=it.tryAdvance(action);
if(!seen && !r) throw e.get();
seen=true;
return r;
}
public Spliterator trySplit() { return null; }
public long estimateSize() { return it.estimateSize(); }
public int characteristics() { return it.characteristics(); }
}, false);
}
这里是一些使用它的示例代码:
List l=Arrays.asList("hello", "world");
nonEmptyStream(l.stream(), ()->new RuntimeException("No strings available"))
.forEach(System.out::println);
nonEmptyStream(l.stream().filter(s->s.startsWith("x")),
()->new RuntimeException("No strings available"))
.forEach(System.out::println);
(高效的)并行执行的问题是支持拆分器需要一个线程安全的方式来通知是否任何一个片段以线程安全的方式看到任何值。然后,最后执行tryAdvance的片段必须意识到它是最后一个(并且它也不能前进)抛出相应的异常。所以我没有添加支持拆分这里。