当前位置: 首页 > 知识库问答 >
问题:

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

杨昆
2023-03-14

如何检查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();
}

共有3个答案

沈琨
2023-03-14

如果您可以在有限的并行能力下生活,那么以下解决方案将起作用:

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

龙隐水
2023-03-14

其他答案和注释是正确的,因为要检查流的内容,必须添加终端操作,从而“消费”流。但是,可以这样做,并将结果返回到流中,而无需缓冲流的全部内容。以下是几个示例:

static <T> Stream<T> throwIfEmpty(Stream<T> stream) {
    Iterator<T> iterator = stream.iterator();
    if (iterator.hasNext()) {
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
    } else {
        throw new NoSuchElementException("empty stream");
    }
}

static <T> Stream<T> defaultIfEmpty(Stream<T> stream, Supplier<T> supplier) {
    Iterator<T> iterator = stream.iterator();
    if (iterator.hasNext()) {
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
    } else {
        return Stream.of(supplier.get());
    }
}

基本上将流转换为Iterator以便在其上调用hasNext(),如果为true,则将Iterator转换回Stream。这是低效的,因为对流的所有后续操作都将通过Iterator的hasNext()Next()方法,这也意味着流被有效地按顺序处理(即使它后来被转换为并行)。然而,这确实允许您在不缓冲其所有元素的情况下测试流。

可能有一种方法可以使用拆分器(Spliterator)而不是迭代器(Iterator)。这可能允许返回的流具有与输入流相同的特性,包括并行运行。

澹台季萌
2023-03-14

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

stream.findAny().isPresent()
 类似资料:
  • 我的想法是: 是最好的办法吗?

  • 我有一个名为< code>Person的对象。 它有几个属性; 我设置了一个person对象,比如< code>Person p = new Person(1,“Joe”);。 1.) 我需要检查对象是否为空;以下表达式是否正确; 2.)我需要知道ID是否包含Int。 但是,java不允许这样做。我该怎么办?

  • 问题内容: 如何检查是否为空? 问题答案: 您自己说过的,请检查它是: 看,PHP非常简单。您可以简单地写下您的想法;) 这种方法很安全。如果未设置(可能,但可能),则可能会给您提供未定义的变量E_NOTICE 。

  • 我需要在JPA查询中传递这个参数。 我如何才能实现这一点,而不是为IS NULL&IS NOT NULL创建2个单独的查询。

  • 我想知道检查列表是否为空的最佳方法是什么。在我的Stream中,我调用两次。它有效,但我不知道它是否正确?它看起来有点难看: 当列表为空并且没有找到任何项目时,我必须抛出错误

  • 问题内容: 如何检查大pandas是否为空?就我而言,如果终端为空,我想在终端打印一些消息。 问题答案: 您可以使用该属性检查其是否为空: 资料来源:pandas文件