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

2022-08-31 07:59:56

如何检查 a 是否为空,如果不是,则作为非终端操作引发异常?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();
}

答案 1

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

stream.findAny().isPresent()

答案 2

其他答案和注释是正确的,因为要检查流的内容,必须添加终端操作,从而“消耗”流。但是,可以执行此操作并将结果转换回流,而无需缓冲流的全部内容。以下是几个例子:

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

基本上将流转换为为了调用它,如果为 true,则将返回转换为 .这是低效的,因为流上的所有后续操作都将通过迭代器和方法,这也意味着流被有效地按顺序处理(即使它后来变得并行)。但是,这允许您在不缓冲其所有元素的情况下测试流。IteratorhasNext()IteratorStreamhasNext()next()

可能有一种方法可以使用 而不是 .这可能允许返回的流具有与输入流相同的特征,包括并行运行。SpliteratorIterator


推荐