Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find which element of the stream does not match the given predicate in allmatch

I want to find out which element is failing the predicate in case of allmatch.

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

Here isEven is false, as element 1 fails the predicate.

I can use forEach over the stream to find which element fails like:

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

Is there a way to figure out which elements fails the predicate in the allmatch when it returns false?

like image 388
sanchitkum Avatar asked Jun 08 '17 06:06

sanchitkum


People also ask

How do you find the element of a stream?

To find an element matching specific criteria in a given list, we: invoke stream() on the list. call the filter() method with a proper Predicate. call the findAny() construct, which returns the first element that matches the filter predicate wrapped in an Optional if such an element exists.

What is stream allMatch?

Stream allMatch(Predicate predicate) returns whether all elements of this stream match the provided predicate. It may not evaluate the predicate on all elements if not necessary for determining the result. This is a short-circuiting terminal operation.

What does findFirst () do in Java stream?

The findFirst() method finds the first element in a Stream. So, we use this method when we specifically want the first element from a sequence. When there is no encounter order, it returns any element from the Stream.

What is the difference between the anyMatch () and findAny () stream methods?

The difference is in the type of the return value: Stream#findAny() : Returns an Optional describing some element of the stream, or an empty Optional if the stream is empty. Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty.


2 Answers

Please remember that allMatch is a short-circuiting operation, meaning that the stream API may return false without finding all the elements that fail the test.

So if you want to find all the failing elements, you might have to do more work than a simple allMatch (as shown by other answers). However, if you only care to find one element that fails the test, use findAny as follows:

Optional<Integer> odd = numbers.stream()
    .filter(n -> n % 2 != 0)
    .findAny();

boolean isEven = !odd.isPresent();

odd.ifPresent(x -> System.out.println(x + " is odd"));
like image 120
Misha Avatar answered Nov 14 '22 21:11

Misha


For this example:

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]}

You could simply log it for example also:

boolean isEven = numbers.stream().allMatch(n -> {
        boolean test = n % 2 == 0;
        if (!test) {
            System.out.println("Failed = " + n);
        }
        return test;
    });

But this might introduce interesting results if you run it in parallel. The output would be un-predictable. That is isEven is still going to return the correct result, but what you see via Syso is completely un-predicatable. Could be :

 Failed = 3
 Failed = 1
 Failed = 5

And on another run could be:

 Failed = 3
like image 33
Eugene Avatar answered Nov 14 '22 21:11

Eugene