I want to compare if any of the objects in a list2
is present in a list1
.
I could iterate over both lists and compare all elements using .contains()
but I am wondering if there is not a more efficient way. I found this and I am trying to implement the suggested method:
List<Item> list1;
List<Item> list2;
boolean anyMatch = list1.stream().anyMatch(x -> x.equals(list2.stream()));
System.out.println(anyMatch);
When I do this I constantly get false
, even when I'd expect a true
. How come?
They do the same job internally, but their return value is different. Stream#anyMatch() returns a boolean while Stream#findAny() returns an object which matches the predicate.
Streams are not modifiable i.e one can't add or remove elements from streams. These are modifiable i.e one can easily add to or remove elements from collections. Streams are iterated internally by just mentioning the operations. Collections are iterated externally using loops.
Java equals() method This method accepts an object to be compared for equality with the list. It returns true if the specified object is equal to the list, else returns false. In the following example, we have create two ArrayList firstList and secondList. Comparing both list by using equals() method, it returns true.
Stream anyMatch() in Java with examples Stream anyMatch(Predicate predicate) 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.
From your comments, you have two lists, list1
and list2
. You want to find out if at least one of the element in list2
is contained in list1
.
With the Stream API, you can acquire a Stream
of list2
. Then, a call anyMatch(predicate)
returns whether one of the element of this stream matches the given predicate, which, in this case, tests whether the element is contained in list1
.
boolean anyMatch = list2.stream().anyMatch(list1::contains);
This uses a method reference as the predicate.
You would have better performance by converting the list1
into a Set
, which guarantees constant-time look-up:
boolean anyMatch = list2.stream().anyMatch(new HashSet<>(list1)::contains);
Although @Tunaki's answer is correct, here's another more concise way (it doesn't use Stream.anyMatch()
method, though):
boolean anyMatch = !Collections.disjoint(list1, list2);
This uses the Collections.disjoint()
method, which returns true
when two collections have no elements in common.
Tunaki's comment regarding performance also applies here: for better performance, the best would be to turn your list1
into a HashSet
, because its contains()
method is O(1)
average. The Collections.disjoint()
method actually checks if any of its arguments is a Set
and iterates over the collection that is not a Set
. So in your case, all you have to do is create a HashSet
from your list1
:
boolean anyMatch = !Collections.disjoint(new HashSet<>(list1), list2);
Note: After all, my answer is only 5 characters shorter that Tunaki's :)
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