Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is anyMatch deterministic like filter + findFirst? [closed]

Is anyMatch deterministic (for an ordered stream) like filter + findFirst? Are there any other differences beside the returning value?

If I have an ordered stream asList("a","b","c").filter(predicate).findFirst() it is guaranteed that the predicate will be evaluated for each element of the stream in the given order ("a" than "b" than "c") until one will match (findFirst). I am wondering if asList("a","b","c").anyMatch(predicate) will also evaluate the predicate in the given order ("a" than "b" than "c")?

like image 462
telebog Avatar asked Aug 26 '19 13:08

telebog


People also ask

Does findFirst have deterministic Behaviour?

The behavior of the findFirst method does not change in the parallel scenario. If the encounter order exists, it will always behave deterministically.

Is findFirst deterministic in Java?

There is not much to be deterministic about here; at least the comparison you are asking for makes little sense. filter. findFirst will return an Optional<T> , so if you care about which element was found, is it really first for an ordered stream? If so, the answer is yes - but it seems you are already aware of that.

What is difference between anyMatch and allMatch?

anyMatch() returns true if any of the elements in a stream matches the given predicate. If the stream is empty or if there's no matching element, it returns false . allMatch() returns true only if ALL elements in the stream match the given predicate.

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

Stream#anyMatch() returns a boolean while Stream#findAny() returns an object which matches the predicate.


3 Answers

There is not much to be deterministic about here; at least the comparison you are asking for makes little sense. filter.findFirst will return an Optional<T>, so if you care about which element was found, is it really first for an ordered stream? If so, the answer is yes - but it seems you are already aware of that.

In case of anyMatch - the determinism is only about the result, which is a boolean, so there is not much to be deterministic about, really; be that for an ordered stream or not. The result will "deterministically" be true/false - that is the only guarantee you get.

If your question whether the stream will be traversed from the beginning or not in case of anyMatch is an entirely different question. That is an implementation detail, of course; but it does not have to be traversed that way. The stream internals could easily have different paths that are taken in case of anyMatch: a totally made-up example, but entirely possible:

Stream.of(6, 5, 4, 3, 2, 1)
      .sorted(Comparator.naturalOrder())
      .anyMatch(x -> x > 4);

A stream internal could keep "in mind" that the min for this stream is 1 and the max is 6, for this anyMatch is could take 6 and test is against max, if that matches, you are done. So the comparison could happen against the last element - 6, which would be different then filter.findFirst - 5.

I highly doubt that such optimizations (that might probably even hurt more than "optimize") would ever be done; but in theory could be possible.

like image 115
Eugene Avatar answered Oct 17 '22 17:10

Eugene


anyMatch returns boolean value true if any elements of the stream match the provided predicate, otherwise returns false where as findFirst returns you Optional<T> which will contain the matching element if it exist else will return empty Optional. You can choose based on what you are trying to do. If you just want to check if the value exist or not then you can use anyMatch as it gives you the value. If you want to find the value and do something with it, you can use findFirst. Following is a small code snippet showing both goes in exact same fashion when used with stream the approach is not predictable when used with parallelStream.

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

class Scratch {
    public static void main(String[] args) {
        List<MyInteger> myIntegers= new ArrayList<>();
        for (int i = 1; i < 10; i++) {
            myIntegers.add(new MyInteger(i));
        }
        System.err.println("----------findFirst------------");
        Optional<MyInteger> result = myIntegers.stream().filter(m -> m.equals(5)).findFirst();
        if(result.isPresent()){
            System.err.println("Matching Record Found: " + result.get());
        }else {
            System.err.println("Matching Record Not Found.");
        }

        System.err.println("----------anyMatch------------");
        System.err.println("anyMatch Result: " + myIntegers.stream().anyMatch(m -> m.equals(5)));
    }
}

class MyInteger {
    private int number;

    public MyInteger(int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        return "MyInteger{" +
                "number=" + number +
                '}';
    }

    boolean equals(int match){
        System.err.println("Matching " + number + " with " + match);
        return number == match;
    }
}

And the output is

----------findFirst------------
Matching 1 with 5
Matching 2 with 5
Matching 3 with 5
Matching 4 with 5
Matching 5 with 5
Matching Record Found: MyInteger{number=5}
----------anyMatch------------
Matching 1 with 5
Matching 2 with 5
Matching 3 with 5
Matching 4 with 5
Matching 5 with 5
anyMatch Result: true
like image 24
Rakesh Avatar answered Oct 17 '22 15:10

Rakesh


Stream anyMatch function returns whether any 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, which returns a boolean value.

    List<Integer> list1 = Arrays.asList(3, 1);
    List<Integer> list2 = Arrays.asList(1, 4, 6, 12, 20);
    boolean b = list1.stream().anyMatch(list2::contains);

The above statement returns false.

Stream Filter return stream of the elements that match the given predicate. This is an intermediate operation. These operations are always lazy i.e, executing an intermediate operation such as filter() does not actually perform any filtering, but instead creates a new stream which when traversed, contains the elements of the initial stream that match the given predicate.

Stream FindFirst is a terminal operation. It returns an Optional the first value encountered in the stream, or an empty Optional if the stream is empty. isPresent is a boolean function that is used to identify if the optional has a value or not.

    List<Integer> list1 = Arrays.asList(3, 11);
    List<Integer> list2 = Arrays.asList(1, 4, 6, 12, 20);

    Optional<Integer> first = list1.stream().filter(list2::contains).findFirst();
    if(first.isPresent())
        System.out.println(first.get());
like image 33
Meghna Avatar answered Oct 17 '22 15:10

Meghna