我希望在allmatch
的情况下找出哪个元素使谓词失败。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean isEven = numbers.stream().allMatch(n-> n % 2 == 0);
此处isEven
为false
,因为元素1
未通过谓词。
我可以在流上使用forEach
来查找哪个元素失败:
numbers.stream().forEach(n -> {
if (n % 2 != 0)
System.out.println(n + "is Odd");
});
有没有办法在allmatch
返回false
时找出哪些元素在谓词中失败?
答案 0 :(得分:5)
对于这个例子:
Map<Boolean, List<Integer>> map = numbers.stream()
.collect(Collectors.partitioningBy(x -> x % 2 == 0));
System.out.println(map); // {false=[1, 3, 5], true=[2, 4]}
您也可以简单地记录它,例如:
boolean isEven = numbers.stream().allMatch(n -> {
boolean test = n % 2 == 0;
if (!test) {
System.out.println("Failed = " + n);
}
return test;
});
但如果你在parallel
中运行它,可能会引入有趣的结果。输出是不可预测的。即isEven
仍会返回正确的结果,但您通过Syso
看到的内容完全无法预测。可能是:
Failed = 3
Failed = 1
Failed = 5
另一次运行可能是:
Failed = 3
答案 1 :(得分:5)
请记住allMatch
是一个短路操作,这意味着流API可能会返回false而不会找到所有未通过测试的元素。
因此,如果您想找到所有失败的元素,您可能需要做更多的工作而不是简单的allMatch
(如其他答案所示)。但是,如果您只想找到一个未通过测试的元素,请使用findAny
,如下所示:
Optional<Integer> odd = numbers.stream()
.filter(n -> n % 2 != 0)
.findAny();
boolean isEven = !odd.isPresent();
odd.ifPresent(x -> System.out.println(x + " is odd"));
答案 2 :(得分:0)
尝试:
List<Integer> notMatchElements = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList());
如果notMatchElements长度等于0 - >全部匹配
其他 - &gt;你没有匹配元素
答案 3 :(得分:0)
您需要拆分这两个动作(过滤掉并验证所有匹配为两个动作)
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> notMatched = numbers
.stream()
.filter(n-> n % 2 != 0)
.collect(Collectors.toList());
boolean isEven = notMatched.isEmpty();
答案 4 :(得分:0)
我建议使用这种方法:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> badNumbers = numbers.stream().filter(n -> n % 2 != 0).collect(Collectors.toList());
在这种情况下,如果所有元素都满足badNumbers
,则n%2 = 0
将为空,否则它将包含不具有的值。
答案 5 :(得分:0)
需要澄清一点:boolean
不是Predicate
。 boolean
是名词,但Predicate
是谓词。所以你的Predicate
更像是这样:
IntPredicate isEven = n -> n % 2 == 0;
boolean numbersAreEven = numbers.stream().allMatch(isEven);
IF 您需要使用Predicate#negate来反转Predicate
,例如:
IntPredicate isOdd = isEven.negate();
boolean numbersAreOdd = numbers.stream().allMatch(isOdd);
IF 您要列出所有奇数,您应该使用Stream#filter,例如:
numbers.stream().filter(isOdd).forEach(System.out::println);
IF 您想要找到第一个奇数,您可以使用Stream#findFirst,例如:
Number odd = numbers.stream().filter(isOdd).findFirst().orElse(null);
IF 无论元素顺序如何,您都希望找到第一个奇数,您可以使用Stream#findAny,例如:
Number odd = numbers.stream().filter(isOdd).findAny().orElse(null);
注意:Stream#findAny和Stream#findFirst都是short-circuiting terminal operation,这意味着只要满足任何intermediate operation,它就会退出。