Comparing two collections using Stream - anyMatch

孤者浪人 提交于 2021-01-26 21:16:23

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!