如何检查 Java 8 Stream 是否为空?

新手上路,请多包涵

我如何检查 Stream 是否为空,如果不是,则作为非终端操作抛出异常?

基本上,我正在寻找与下面的代码等效的东西,但没有具体化中间的流。特别是,检查不应发生在终端操作实际使用流之前。

 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();
}

原文由 Cephalopod 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

如果您可以忍受有限的并行能力,以下解决方案将起作用:

 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);
}

下面是一些使用它的示例代码:

 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 的最后一个片段必须意识到它是最后一个(并且它也无法前进)抛出适当的异常。所以这里我没有添加对拆分的支持。

原文由 Holger 发布,翻译遵循 CC BY-SA 4.0 许可协议

在许多情况下这可能就足够了

stream.findAny().isPresent()

原文由 kenglxn 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题