ArrayList 与 HashSet 中的 removeAll()
removeAll() in ArrayList vs HashSet
我发现对于相当大的数组(超过 1000 个条目),方法 A.removeAll(B)
在 HashSet
上比在 ArrayList
上快得多。
您是否知道这些方法是如何实现的,以及这如何解释这种差异?
一个集合(因此 HashSet
也是如此)最多包含 B
的一个元素,并且由于 HashSet
使用散列,因此定位和删除该元素非常有效。因此,整体复杂度应该是 O(1)
用于删除所有(即一个)B
.
列表可以在任何位置包含任意数量的 B
,因此删除所有 B
必须检查所有元素。总体复杂度为 O(n)
,因为必须检查每个元素是否为 B
。
编辑:
如果 B
表示一个 collection/array,即一组多个元素,您需要将上述复杂度乘以 B
的大小 m
,所以您HashSet
会得到 O(m)
,列表会得到 O(n * m)
。
编辑 2:
请注意,如果您有一个排序列表,复杂性可能会降低到 O(log(n))
或 O(log(n) * m)
。为此,删除实际元素的代码必须 知道 列表已排序,但由于不能保证 ArrayList
已排序,因此无法进行优化。
基本上,两者的原因是这些特定实现试图为其各自的操作实现的时间复杂度。
ArrayList
移除方法的时间复杂度为 O(n - index)
source from When to use LinkedList over ArrayList?
虽然 HashSet
的 remove 方法提供恒定的时间复杂度 O(1)
source from Hashset vs Treeset
我发现对于相当大的数组(超过 1000 个条目),方法 A.removeAll(B)
在 HashSet
上比在 ArrayList
上快得多。
您是否知道这些方法是如何实现的,以及这如何解释这种差异?
一个集合(因此 HashSet
也是如此)最多包含 B
的一个元素,并且由于 HashSet
使用散列,因此定位和删除该元素非常有效。因此,整体复杂度应该是 O(1)
用于删除所有(即一个)B
.
列表可以在任何位置包含任意数量的 B
,因此删除所有 B
必须检查所有元素。总体复杂度为 O(n)
,因为必须检查每个元素是否为 B
。
编辑:
如果 B
表示一个 collection/array,即一组多个元素,您需要将上述复杂度乘以 B
的大小 m
,所以您HashSet
会得到 O(m)
,列表会得到 O(n * m)
。
编辑 2:
请注意,如果您有一个排序列表,复杂性可能会降低到 O(log(n))
或 O(log(n) * m)
。为此,删除实际元素的代码必须 知道 列表已排序,但由于不能保证 ArrayList
已排序,因此无法进行优化。
基本上,两者的原因是这些特定实现试图为其各自的操作实现的时间复杂度。
ArrayList
移除方法的时间复杂度为 O(n - index)
source from When to use LinkedList over ArrayList?
虽然 HashSet
的 remove 方法提供恒定的时间复杂度 O(1)
source from Hashset vs Treeset