让我们仔细阅读代码。该方法继承自 和 (至少在 OpenJDK 中)如下所示:retainAll
AbstractCollection
public boolean retainAll(Collection<?> c) {
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
这里有一个很大的注意事项,我们循环并调用 。因此,时间复杂度是调用 where 和 最多调用 。this.iterator()
c.contains
n
c.contains
n = this.size()
n
it.remove()
重要的是,该方法被调用在另一个方法上,因此复杂性取决于另一个方法的复杂性。contains
Collection
Collection
contains
所以,同时:
Set<String> common = new HashSet<>(Arrays.asList(a));
common.retainAll(new HashSet<>(Arrays.asList(b)));
将是 ,因为 和 都是 (摊销)。O(a.length)
HashSet.contains
HashSet.remove
O(1)
如果您要致电
common.retainAll(Arrays.asList(b));
然后由于 on 这将成为 - 即通过花费花费将数组复制到一个你实际上使调用要快得多。O(n)
contains
Arrays.ArrayList
O(a.length * b.length)
O(n)
HashSet
retainAll
就空间复杂性而言,不需要额外的空间(超出),但是您的调用实际上在空间方面非常昂贵,因为您分配了两个实际上已经完全成熟的新实现。Iterator
retainAll
HashSet
HashMap
还有两件事可以注意:
- 没有理由从元素中分配a - 一个更便宜的集合,也可以从中间删除,例如可以使用。(内存和构建时间更便宜 - 未构建哈希表)
HashSet
a
O(1)
LinkedList
- 当您创建新的集合实例时,您的修改将丢失,并且仅返回 。
b.size()