查找流的哪个元素与allmatch中的给定谓词不匹配

时间:2017-06-08 06:57:20

标签: java java-8 java-stream

我希望在allmatch的情况下找出哪个元素使谓词失败。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean isEven = numbers.stream().allMatch(n-> n % 2 == 0);

此处isEvenfalse,因为元素1未通过谓词。

我可以在流上使用forEach来查找哪个元素失败:

numbers.stream().forEach(n -> {
            if (n % 2 != 0)
                System.out.println(n + "is Odd");
        });

有没有办法在allmatch返回false时找出哪些元素在谓词中失败?

6 个答案:

答案 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不是Predicateboolean名词,但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#findAnyStream#findFirst都是short-circuiting terminal operation,这意味着只要满足任何intermediate operation,它就会退出。