如何检查Java 8 Stream是否为空? [英] How to check if a Java 8 Stream is empty?
问题描述
如何检查 Stream
是否为空并且如果不是,则抛出异常,作为非终端操作?
How can I check if a Stream
is empty and throw an exception if it's not, as a non-terminal operation?
基本上,我正在寻找与下面的代码等效的东西,但没有实现中间的流。特别是,在终端操作实际消耗流之前不应进行检查。
Basically, I'm looking for something equivalent to the code below, but without materializing the stream in-between. In particular, the check should not occur before the stream is actually consumed by a terminal operation.
public Stream<Thing> getFilteredThings() {
Stream<Thing> stream = getThings().stream()
.filter(Thing::isFoo)
.filter(Thing::isBar);
return nonEmptyStream(stream, () -> {
throw new RuntimeException("No foo bar things available")
});
}
private static <T> Stream<T> nonEmptyStream(Stream<T> stream, Supplier<T> defaultValue) {
List<T> list = stream.collect(Collectors.toList());
if (list.isEmpty()) list.add(defaultValue.get());
return list.stream();
}
推荐答案
如果你能活得有限并行功能,以下解决方案将起作用:
If you can live with limited parallel capablilities, the following solution will work:
private static <T> Stream<T> nonEmptyStream(
Stream<T> stream, Supplier<RuntimeException> e) {
Spliterator<T> it=stream.spliterator();
return StreamSupport.stream(new Spliterator<T>() {
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<T> trySplit() { return null; }
public long estimateSize() { return it.estimateSize(); }
public int characteristics() { return it.characteristics(); }
}, false);
}
以下是一些使用它的示例代码:
Here is some example code using it:
List<String> 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);
(高效)并行执行的问题是支持拆分 Spliterator
需要一种线程安全的方式来注意其中一个片段是否以线程安全的方式看到了任何值。然后执行 tryAdvance
的最后一个片段必须意识到它是最后一个(并且它也无法前进)抛出适当的异常。所以我没有在这里添加对拆分的支持。
The problem with (efficient) parallel execution is that supporting splitting of the Spliterator
requires a thread-safe way to notice whether either of the fragments has seen any value in a thread-safe manner. Then the last of the fragments executing tryAdvance
has to realize that it is the last one (and it also couldn’t advance) to throw the appropriate exception. So I didn’t add support for splitting here.
这篇关于如何检查Java 8 Stream是否为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!