java集合中元素比较的性能

时间:2015-06-08 14:11:13

标签: java performance collections

问题:

给定两个Collection<?>,检查两者是否包含相同的元素。

  • 假设该集合的实际实现未知
  • 假设元素不以相同的顺序出现
  • 假设在同一个集合中没有出现过两次元素

解决方案1:

boolean equals = c1.containsAll(c2) && c2.containsAll(c1);

解决方案2:

boolean equals = new HashSet<?>(c1).equals(new HashSet<?>(c2));

我认为解决方案2 解决方案1 ​​ O(n)更高效( O(n)) 2))。

我是对还是错过了什么?

2 个答案:

答案 0 :(得分:8)

这些的大O复杂性是正确的,解决方案1涉及迭代另一个列表中每个项目的一个列表(O (n)),即O (n^2)。解决方案2涉及两个O (n)个副本,并在一个集合(O (n))上进行迭代,并对另一个集合进行O (1) .contains()检查。总而言之,那只是O (n)

但是根据你的约束,你可以做得更好(不是渐近更好,只是更好的实现)。

  • 由于我们假设没有重复元素,因此无需进行第二次.containsAll()检查。只需检查它们的大小是否相同(可能是O (n),但仍然比复制O (n^2)检查更好)然后执行.containsAll()

  • 无需将c2转换为Set,因为它会反复进行迭代;只需转换c1并使用.containsAll()

  • 您可以使用instanceof Set来测试c1c2是否已经是Set,并使用该对象的.containsAll()方法;这将在O (n)时间运行,即使其他对象不是一个集合,也可以避免解决方案2具有的复制开销。

答案 1 :(得分:2)

如dimo414所述,一般来说,是的。但你总是可以做得更好(不是渐近更好,只是更快)。它变得更加复杂:

if (c1.size() != c2.size()) {
    return false;
} else if (c1 instanceof Set) {
    return c1.containsAll(c2);
} else if (c2 instanceof Set) {
    return c2.containsAll(c1);
} else {
    return new HashSet<>(c1).containsAll(c2);
}

还有一些慢size的集合,您可能需要特别处理......