使用Stream比较两个集合 - anyMatch

k88*_*k88 8 java java-stream

我想比较a中的任何对象list2是否存在于a中list1.

我可以遍历两个列表并比较所有元素,.contains()但我想知道是否有更有效的方法.我找到了这个,我正在尝试实现建议的方法:

List<Item> list1;
List<Item> list2;

boolean anyMatch = list1.stream().anyMatch(x -> x.equals(list2.stream()));
System.out.println(anyMatch);
Run Code Online (Sandbox Code Playgroud)

当我这样做false时,我会不断地得到,即使在我期待的时候true.怎么会?

Tun*_*aki 11

根据您的评论,您有两个列表,list1list2.你想,如果在元件的至少一个,找出list2包含在list1.

随着流API,你可以获取Streamlist2.然后,调用anyMatch(predicate)返回此流的一个元素是否与给定谓词匹配,在这种情况下,测试是否包含该元素list1.

boolean anyMatch = list2.stream().anyMatch(list1::contains);
Run Code Online (Sandbox Code Playgroud)

这使用方法引用作为谓词.

通过转换list1为a 可以获得更好的性能Set,从而保证了恒定时间的查找:

boolean anyMatch = list2.stream().anyMatch(new HashSet<>(list1)::contains);
Run Code Online (Sandbox Code Playgroud)


Fed*_*ner 8

虽然@Tinaki的答案是正确的,但这是另一种更简洁的方法(Stream.anyMatch()尽管它不使用方法):

boolean anyMatch = !Collections.disjoint(list1, list2);
Run Code Online (Sandbox Code Playgroud)

这使用了该Collections.disjoint()方法,true当两个集合没有共同的元素时返回.

Tunaki关于性能的评论也适用于此:为了获得更好的性能,最好将你list1变成a HashSet,因为它的contains()方法是O(1)平均的.该Collections.disjoint()方法实际上检查它的任何参数是否为a Set并迭代不是a的集合Set.所以在你的情况下,你所要做的就是HashSet从你的list1:创建一个:

boolean anyMatch = !Collections.disjoint(new HashSet<>(list1), list2);
Run Code Online (Sandbox Code Playgroud)

注意:毕竟,我的答案只比Tunaki的短了5个字符:)


Tan*_*ury 8

  • 使用 Java 8 流 API
boolean isAnyMatch = list2.stream().anyMatch(list1::contains);
Run Code Online (Sandbox Code Playgroud)
  • 使用 Collection 类方法
boolean isAnyMatch = !Collections.disjoint(new HashSet(list1), list2);
Run Code Online (Sandbox Code Playgroud)

无论如何,在比较之前将列表转换为设置将提供更快的输出。