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

我有一个流,想检查是否所有匹配filter。 如果全部匹配,则返回true

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

我怎样才能做到这一点?

示例代码:

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

你可以用

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

表达了意图。 我们将每个元素映射到一个boolean值,表示它是否与逻辑操作匹配并减少所有元素,如果所有元素都为true ,则将产生true 。 如果没有元素, reduce将返回一个空的可Optional ,我们使用orElse(false)将其映射为false

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

仍然支持短路的解决方案可能会进一步发展:

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

这是Eugene的答案的变体,但它并没有松散特征或并行性,一般来说可能更有效。

以下代码将起作用(我对其进行了测试)。

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

怎么运行的? 我们使用reduce操作来检查每个元素是否与谓词匹配,如果失败,我们会继续返回失败的元素(在三元操作中)。 最后,我们将减少的Whatever对象映射到布尔值,如果它是真的:那么所有匹配的并且这不是空的( orElse(false) )。

如果您可以丢失特性和并行性,例如:

  public static boolean validate(Stream stream) { Iterator it = stream.iterator(); if (!it.hasNext()) { return false; } return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, 0), false) .peek(System.out::println) .allMatch(x -> x.contains("a")); } 

试试看

 boolean[] flag = new boolean[1]; return stream.peek(t -> flag[0] = true).allMatch(Whatever::someCheck) && flag[0] 

我已经添加了两个答案,我现在已经删除但问题一直在唠叨我,所以我给了它第三次尝试,这次它的工作包括保持allMatch 。 这是方法validate的代码。

 public static boolean validate(Stream stream) { final boolean[] streamNotEmpty = new boolean[1]; return stream.filter(elem -> { streamNotEmpty[0] = true; return true; }).allMatch(Whatever::someCheck) && streamNotEmpty[0]; } 

更短的版本

 public static boolean validate(Stream stream) { final boolean[] streamNotEmpty = new boolean[1]; return stream.allMatch(elem -> { streamNotEmpty[0] = true; return elem.someCheck(); }) && streamNotEmpty[0]; } 

这背后的想法是我们想要知道流中是否至少有一个元素,所以我创建了一个final boolean[] ,其中值在filter-call中被更改。 因此,在流处理结束时,我们可以检查流是否为空,并在返回结果时采取相应措施。

这是一个完整的类,包括测试用例来certificate – 这次终于 – 我提供了一个有效的解决方案。

 import java.util.ArrayList; import java.util.stream.Stream; public class StreamTest { public static boolean validate(Stream stream) { final boolean[] streamNotEmpty = new boolean[1]; return stream.allMatch(elem -> { streamNotEmpty[0] = true; return elem.someCheck(); }) && streamNotEmpty[0]; } static class Whatever { private boolean checkResult; public Whatever() { this(false); } public Whatever(boolean b) { this.checkResult = b; } public boolean someCheck() { return checkResult; } } public final static void main(String[] args) { ArrayList list = new ArrayList<>(); System.out.println("empty list: " + validate(list.stream())); System.out.println("empty list parallel: " + validate(list.parallelStream())); for (int i = 0; i < 10000; i++) { list.add(new Whatever(true)); } System.out.println("non empty true list: " + validate(list.stream())); System.out.println("non empty true list parallel: " + validate(list.parallelStream())); for (int i = 0; i < 10000; i += 1000) { list.add(new Whatever(false)); } System.out.println("non empty false list: " + validate(list.stream())); System.out.println("non empty false list parallel: " + validate(list.parallelStream())); } } 

执行时的输出是:

empty list: false empty list parallel: false non empty true list: true non empty true list parallel: true non empty false list: false non empty false list parallel: false

 return !stream.filter(Whatever::someCheck).collect(Collectors.toList()).isEmpty()