很明显,泛型HashSet<T>类的搜索性能要高于泛型List<T>类。只需将基于哈希的键与List<T>类中的线性方法进行比较。
然而,计算哈希键本身可能需要一些CPU周期,因此对于少量的项,线性搜索可以成为HashSet<T>的真正替代方法。
我的问题是:盈亏平衡在哪里?
为了简化场景(公平起见),让我们假设List<T>类使用元素的Equals()方法来标识一个项。
很明显,泛型HashSet<T>类的搜索性能要高于泛型List<T>类。只需将基于哈希的键与List<T>类中的线性方法进行比较。
然而,计算哈希键本身可能需要一些CPU周期,因此对于少量的项,线性搜索可以成为HashSet<T>的真正替代方法。
我的问题是:盈亏平衡在哪里?
为了简化场景(公平起见),让我们假设List<T>类使用元素的Equals()方法来标识一个项。
当前回答
比较两种表现不同的结构的性能本质上是没有意义的。使用传达意图的结构。即使你说List<T>不会有重复,迭代顺序也无关紧要,使其与HashSet<T>相当,但使用List<T>仍然是一个糟糕的选择,因为它的容错能力相对较低。
也就是说,我将检查性能的其他方面,
+------------+--------+-------------+-----------+----------+----------+-----------+
| Collection | Random | Containment | Insertion | Addition | Removal | Memory |
| | access | | | | | |
+------------+--------+-------------+-----------+----------+----------+-----------+
| List<T> | O(1) | O(n) | O(n) | O(1)* | O(n) | Lesser |
| HashSet<T> | O(n) | O(1) | n/a | O(1) | O(1) | Greater** |
+------------+--------+-------------+-----------+----------+----------+-----------+
尽管在这两种情况下加法都是O(1),但在HashSet中它会相对较慢,因为它涉及到在存储哈希代码之前预计算哈希代码的成本。 HashSet优越的可伸缩性有内存成本。每个条目连同它的哈希代码一起存储为一个新对象。这篇文章可能会给你一个想法。
其他回答
这取决于很多因素……列表实现,CPU架构,JVM,循环语义,equals方法的复杂性,等等…当列表变得足够大,可以有效地进行基准测试(1000多个元素)时,基于哈希的二进制查找就可以轻松地击败线性搜索,并且差异只会在此基础上扩大。
希望这能有所帮助!
使用HashSet<>还是List<>取决于您需要如何访问您的集合。如果你需要保证项目的顺序,使用一个列表。如果没有,请使用HashSet。让微软去担心他们的哈希算法和对象的实现吧。
HashSet将访问项目而不必枚举集合(复杂度为O(1)或接近它),并且由于List保证顺序,与HashSet不同,一些项目将必须被枚举(复杂度为O(n))。
比较两种表现不同的结构的性能本质上是没有意义的。使用传达意图的结构。即使你说List<T>不会有重复,迭代顺序也无关紧要,使其与HashSet<T>相当,但使用List<T>仍然是一个糟糕的选择,因为它的容错能力相对较低。
也就是说,我将检查性能的其他方面,
+------------+--------+-------------+-----------+----------+----------+-----------+
| Collection | Random | Containment | Insertion | Addition | Removal | Memory |
| | access | | | | | |
+------------+--------+-------------+-----------+----------+----------+-----------+
| List<T> | O(1) | O(n) | O(n) | O(1)* | O(n) | Lesser |
| HashSet<T> | O(n) | O(1) | n/a | O(1) | O(1) | Greater** |
+------------+--------+-------------+-----------+----------+----------+-----------+
尽管在这两种情况下加法都是O(1),但在HashSet中它会相对较慢,因为它涉及到在存储哈希代码之前预计算哈希代码的成本。 HashSet优越的可伸缩性有内存成本。每个条目连同它的哈希代码一起存储为一个新对象。这篇文章可能会给你一个想法。
视情况而定。如果确切的答案真的很重要,那就做一些分析,找出答案。如果你确定你永远不会有超过一定数量的元素在集合中,使用List。如果数字是无界的,则使用HashSet。
您没有考虑到的一个因素是GetHashcode()函数的健壮性。有了完美的哈希函数,HashSet显然会有更好的搜索性能。但是随着哈希函数的减少,HashSet搜索时间也会减少。