如何匹配流元素,但如果不存在,则返回 false?

2022-09-04 08:44:48

我有一个流,并想检查是否都与过滤器匹配。如果全部匹配,则返回 。true

但是,如果流是空的,我想返回。false

我该怎么做?

示例代码:

public boolean validate(Stream<Whatever> stream) {
  // Problem: returns **true** if stream empty.
  // How can **false** be returned if stream is empty?
  return stream.allMatch(Whatever::someCheck);
}

答案 1

您可以使用

public boolean validate(Stream<Whatever> stream) {
    return stream.map(Whatever::someCheck).reduce(Boolean::logicalAnd).orElse(false);
}

它表达了意图。我们将每个元素映射到一个值,表示它是否匹配,并使用逻辑运算减少所有元素,这将产生所有元素。 如果没有元素,将返回一个空,我们按预期映射到使用 。booleantruetruereduceOptionalfalseorElse(false)

唯一的缺点是这是非短路的,即不会在第一个不匹配元件处立即停止。

仍然支持短路的解决方案可能会更加完善:

public boolean validate(Stream<Whatever> stream) {
    boolean parallel = stream.isParallel();
    Spliterator<Whatever> sp = stream.spliterator();
    if(sp.getExactSizeIfKnown() == 0) return false;
    Stream.Builder<Whatever> b = Stream.builder();
    if(!sp.tryAdvance(b)) return false;
    return Stream.concat(b.build(), StreamSupport.stream(sp, parallel))
        .allMatch(Whatever::someCheck);
}

这是Eugene答案的变体,但它不会失去特征或并行性,并且总体上可能更有效率。


答案 2

以下代码将起作用(我测试了它)。

public static boolean validate(Stream<Whatever> stream) {
    return stream.reduce((whatever1, whatever2) -> Whatever.someCheck(whatever1) ? whatever2 : whatever1)
            .map(Whatever::someCheck).orElse(false);
}

它是如何工作的?我们使用操作来检查每个元素是否与谓词匹配,如果它失败,我们继续返回失败的元素(在三元操作中)。最后,我们将简化的对象映射到布尔值,如果它是真的:那么全部匹配,这不是空的()。reduceWhateverorElse(false)


推荐