问题
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?
回答1:
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);
回答2:
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 :)
回答3:
- Using Java 8 stream api
boolean isAnyMatch = list2.stream().anyMatch(list1::contains);
- Using Collection class method
boolean isAnyMatch = !Collections.disjoint(new HashSet(list1), list2);
Anyway converting list to set before comparing will give faster output.
来源:https://stackoverflow.com/questions/36670568/comparing-two-collections-using-stream-anymatch