很明显,泛型HashSet<T>类的搜索性能要高于泛型List<T>类。只需将基于哈希的键与List<T>类中的线性方法进行比较。
然而,计算哈希键本身可能需要一些CPU周期,因此对于少量的项,线性搜索可以成为HashSet<T>的真正替代方法。
我的问题是:盈亏平衡在哪里?
为了简化场景(公平起见),让我们假设List<T>类使用元素的Equals()方法来标识一个项。
很明显,泛型HashSet<T>类的搜索性能要高于泛型List<T>类。只需将基于哈希的键与List<T>类中的线性方法进行比较。
然而,计算哈希键本身可能需要一些CPU周期,因此对于少量的项,线性搜索可以成为HashSet<T>的真正替代方法。
我的问题是:盈亏平衡在哪里?
为了简化场景(公平起见),让我们假设List<T>类使用元素的Equals()方法来标识一个项。
当前回答
这取决于很多因素……列表实现,CPU架构,JVM,循环语义,equals方法的复杂性,等等…当列表变得足够大,可以有效地进行基准测试(1000多个元素)时,基于哈希的二进制查找就可以轻松地击败线性搜索,并且差异只会在此基础上扩大。
希望这能有所帮助!
其他回答
You're looking at this wrong. Yes a linear search of a List will beat a HashSet for a small number of items. But the performance difference usually doesn't matter for collections that small. It's generally the large collections you have to worry about, and that's where you think in terms of Big-O. However, if you've measured a real bottleneck on HashSet performance, then you can try to create a hybrid List/HashSet, but you'll do that by conducting lots of empirical performance tests - not asking questions on SO.
比较两种表现不同的结构的性能本质上是没有意义的。使用传达意图的结构。即使你说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优越的可伸缩性有内存成本。每个条目连同它的哈希代码一起存储为一个新对象。这篇文章可能会给你一个想法。
使用HashSet<>还是List<>取决于您需要如何访问您的集合。如果你需要保证项目的顺序,使用一个列表。如果没有,请使用HashSet。让微软去担心他们的哈希算法和对象的实现吧。
HashSet将访问项目而不必枚举集合(复杂度为O(1)或接近它),并且由于List保证顺序,与HashSet不同,一些项目将必须被枚举(复杂度为O(n))。
您没有考虑到的一个因素是GetHashcode()函数的健壮性。有了完美的哈希函数,HashSet显然会有更好的搜索性能。但是随着哈希函数的减少,HashSet搜索时间也会减少。
您可以使用HybridDictionary自动检测断点,并接受空值,使其本质上与HashSet相同。