如何检查 Java 8 Stream 是否为空? [英] How to check if a Java 8 Stream is empty?

查看:151
本文介绍了如何检查 Java 8 Stream 是否为空?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为非终端操作,如何检查 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆