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")?
The behavior of the findFirst method does not change in the parallel scenario. If the encounter order exists, it will always behave deterministically.
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.
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.
Stream#anyMatch() returns a boolean while Stream#findAny() returns an object which matches the predicate.
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.
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
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With