【发布时间】:2012-04-17 21:55:21
【问题描述】:
我今天在一些编码过程中发现了containsAll()(List 接口方法),它看起来很漂亮。有谁知道这在性能/迭代方面的成本是多少?
documentation 在这方面提供的不多。
【问题讨论】:
标签: java arrays list interface
我今天在一些编码过程中发现了containsAll()(List 接口方法),它看起来很漂亮。有谁知道这在性能/迭代方面的成本是多少?
documentation 在这方面提供的不多。
【问题讨论】:
标签: java arrays list interface
.equals(..) 将当前元素与它们进行比较(注意:这是关于列表,正如您在问题中指定的那样。其他集合的行为不同)所以它是 O(n*m),其中 n 和 m 是两个集合的大小。
public boolean containsAll(Collection<?> c) {
Iterator<?> e = c.iterator();
while (e.hasNext())
if (!contains(e.next()))
return false;
return true;
}
【讨论】:
contains() 的通用实现,但HashSet/HashMap 在O(1) 中完成,任何排序的集合都可能在O(logn) 中完成。
Collection.containsAll() 的原始定义上,它被 List.containsAll() 覆盖。
使用来源,卢克 :)
编辑:正如 Bozho 指出的那样,您问的是 List.containsAll() 覆盖 Collection.containsAll()。下面的漫谈主要与后者有关:
大多数Collection 类将使用implementation of containsAll from AbstractCollection,它是这样的:
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
但不能保证某些实现会完全不同——这可能会导致更好或更差的运行时行为。
containsAll 的上述实现将至少为 O(n),其中 n 是您传入的 Collection 参数中的项目数,加号无论contains 需要什么时间:
HashSet/HashMap,这可能是 O(1)(最好的情况,没有冲突),所以 containsAll 的整体运行时间仍然是 O(n)ArrayList,contains 将占用 O(m),其中 m 是列表中的项目数(不是参数),因此 containsAll 的总时间为 O(n*m)
【讨论】:
addAll 的实现,而不是containsAll。但是 OP:对于大多数实现,containsAll 成本 O(n^2);它没有做任何特别酷的事情。
List 实现。 containsAll 通常需要 O(n) 乘以 contains 查询的成本。
如果您正在调用 A.containsAll(B)
openjdk 迭代 B 调用 A.contains(b) 的所有元素。
A.contains(b) 迭代 A 的所有元素,调用 a.equals(b)
这是来自open jdk 7的源代码
【讨论】:
contains() 以提供更好的实现。想想HashSet。
考虑
n.ContainsAll(m)
最好的情况是 O(m),如果 n 是一个完美的哈希集。
考虑到未排序的列表,我可以提出一个 O(n*log(n) + m*log(m)) 算法
【讨论】: