类似于';包含任何';对于Java集?

类似于';包含任何';对于Java集?,java,Java,我有两套,A和B,类型相同 我必须找出A是否包含集合B中的任何元素 在不迭代集合的情况下,最好的方法是什么? 集合库有contains(object)和containsAll(collection),但没有containsAny(collection),您可以使用方法获得两个集合的交集。在集合界面中使用retainal()。此方法提供两个集合中常用元素的交集。有关更多信息,请参阅API文档。我建议从集合a创建一个HashMap,然后迭代集合B并检查B的任何元素是否在a中。这将在O(| a |+|

我有两套,A和B,类型相同

我必须找出A是否包含集合B中的任何元素

在不迭代集合的情况下,最好的方法是什么?
集合库有
contains(object)
containsAll(collection)
,但没有
containsAny(collection)
,您可以使用方法获得两个集合的交集。

在集合界面中使用
retainal()
。此方法提供两个集合中常用元素的交集。有关更多信息,请参阅API文档。

我建议从集合a创建一个
HashMap
,然后迭代集合B并检查B的任何元素是否在a中。这将在
O(| a |+| B |)时间内运行(因为不会发生冲突),而
retainal(集合c)
必须在
O(| a |*| B |)时间内运行
时间。

有一个粗略的方法可以做到这一点。 当且仅当A集合包含比调用更多的B元素时

A.removeAll(B)
将修改一个集合。在这种情况下,removeAll将返回true(如中所述)。但您可能不想修改集合,因此可能会考虑对副本执行操作,如下所示:

new HashSet(A).removeAll(B)
如果两个集合不是不同的,即它们有非空的交集,则返回值为真

另请参见

不起作用?从文件中:

如果两个指定集合没有共同的元素,则返回
true


因此,如果集合包含任何公共元素,该方法将返回
false

实现集合containsAny的一个好方法是使用番石榴

containsAny
将返回一个
boolean
,因此调用如下所示:

Sets.intersection(set1, set2).isEmpty()

如果集合不相交,则返回true,否则返回false。此操作的时间复杂度可能比Retainal稍好,因为您不必进行任何克隆来避免修改原始集

apachecommons有一个方法。

Stream::anyMatch
因为Java8可以使用

我使用org.apache.commons.collections.CollectionUtils

就这些 如果两个集合中至少有一个元素,则返回true



简单易用,函数名称更具启发性。

如果避免迭代的目的是为了提高效率,
retainal
可能没有帮助。它在
AbstractCollection
iterates.yshavit中的实现是正确的。考虑到O.P.正在查看两个集合中是否存在任何元素,在最佳情况下,适当的算法将有一个
O(1)
运行时间,而
retainal
将有一个与
O(N)
类似的东西(它将仅取决于1个集合的大小)最佳情况下的运行时间。您是为了提高效率,还是为了保持代码整洁而避免迭代?在大多数情况下,需要保留原始集,因此为了使用
retainal
,有必要复制原始集。然后按照建议使用
HashSet
更有效。这是一种状态更改,而不是条件检查。与其他解决方案相比,更喜欢这种解决方案,因为它不会修改任何一个集合或创建新的集合。它是标准的JRE,可用于任何集合,而不仅仅是集合。我认为这不是最快的,当找到交叉点的第一个元素时,它不会短路。实际上,它会在找到第一个公共点时立即短路element@Xipo这是对的。检查使用这种方法的唯一缺点是必须包含番石榴库。我认为这并不是缺点,因为google collection API非常强大。@Didierr大多数Guava Collections实用程序函数,包括这一个,都返回数据结构的视图。因此,在这种情况下,不必担心“构建场景”。在这里阅读实现很有趣,并且/或者可以看到javadoc:@mohammaddnan另一个缺点是,它计算完整的交集-如果set1和set2非常大,这将需要大量的资源(CPU和内存方面)而不仅仅是检查他们是否有共同点。@Mohammaddnan这不是唯一的缺点。在
containsAny
逻辑中,您应该(如果不是必须的话)在找到匹配项后立即返回,但此方法将一直运行,直到在两个集合中都达到
数据结束为止这正是我要寻找的!谢谢:-)我还不知道可以将变量与::语法一起使用@blevert,你能解释一下anyMatch内部发生了什么吗?@Cristiano这里,
anyMatch
将从
setA
流式传输所有元素,并对所有元素调用
setB.contains()
。如果为任何元素返回“true”,则表达式作为一个整体将计算为true。希望这有帮助。@Cristiano这是可行的,但是如果
setA
太大,效率就低了。正确的答案是调用
Collections.disjoint
。使用这种方法的语法很漂亮。您还可以执行
CollectionUtils.containsAny(mySet,“value1”、“value2”)
setA.stream().anyMatch(setB::contains)
CollectionUtils.containsAny(someCollection1, someCollection2)