HashSet与列表性能

时间:2020-03-06 14:53:52  来源:igfitidea点击:

显然,泛型HashSet <T>类的搜索性能高于泛型List <T>类。只需在List <T>类中将基于散列的密钥与线性方法进行比较即可。

但是,计算散列键本身可能会花费一些CPU周期,因此对于少量项,线性搜索可以真正替代" HashSet <T>"。

我的问题:收支平衡在哪里?

为了简化场景(公平地说),我们假设List <T>类使用元素的Equals()方法来标识项目。

解决方案

这取决于。如果确切的答案确实很重要,请进行分析并找出答案。如果我们确定集合中的元素数量绝对不会超过一定数量,请使用列表。如果数字是无界的,请使用HashSet。

收支平衡将取决于计算哈希的成本。哈希运算可以很简单,也可以不是……:-)总是有System.Collections.Specialized.HybridDictionary类可以不必担心盈亏平衡点。

取决于许多因素...列表实现,CPU体系结构,JVM,循环语义,equals方法的复杂性等...到列表变得足够大以有效进行基准测试(1000多个元素)时,基于哈希的二进制文件查找胜过线性搜索,而差异仅从那里扩大。

希望这可以帮助!

取决于我们要散列的内容。如果键是整数,则在HashSet更快之前,我们可能不需要很多项目。如果将其键入字符串,则速度会变慢,具体取决于输入字符串。

当然,我们可以轻松地提高基准吗?

答案一如既往地是"取决于"。我以我们正在谈论的C#标签为基础。

你最好的选择是确定

  • 一组数据
  • 使用要求

并编写一些测试用例。

它还取决于我们对列表进行排序的方式(如果对列表进行了排序),需要进行哪种比较,对列表中的特定对象执行"比较"操作需要多长时间,甚至取决于我们打算如何使用列表。收藏。

通常,最佳选择不是基于我们正在使用的数据大小,而是我们打算如何访问它。我们是否具有与特定字符串或者其他数据相关联的每条数据?基于散列的集合可能是最好的。我们存储的数据顺序是否重要,还是需要同时访问所有数据?定期列出可能会更好。

额外的:

当然,我的上述评论假设"性能"意味着数据访问。还有其他需要考虑的问题:当我们说"表现"时,我们正在寻找什么?表现个人价值在找吗?它是对大型(10000、100000或者更多)值集的管理吗?它是用数据填充数据结构的性能吗?删除数据?访问单个数据位?替换值?遍历值?内存使用情况?数据复制速度?例如,如果我们通过字符串值访问数据,但是主要性能要求是最小化内存使用量,那么我们可能会遇到冲突的设计问题。

使用HashSet <>还是List <>取决于我们需要如何访问集合。如果我们需要保证项目的顺序,请使用列表。如果不这样做,请使用HashSet。让Microsoft担心其哈希算法和对象的实现。

HashSet将访问项目,而不必枚举集合(O(1)或者其附近的复杂性),并且由于List保证顺序,与HashSet不同,某些项目将必须枚举(O(n)的复杂性)。

我们未考虑的一个因素是GetHashcode()函数的健壮性。有了完善的哈希函数,HashSet显然将具有更好的搜索性能。但是随着哈希函数的减少,HashSet的搜索时间也会减少。

我们正在看这个错误。是的,对列表的线性搜索将击败HashSet的少量项目。但是性能差异通常对于那么小的集合无关紧要。通常,我们需要担心的是大型收藏,这就是Big-O的想法。但是,如果我们测量了HashSet性能的真正瓶颈,则可以尝试创建混合的List / HashSet,但是我们可以通过进行大量的经验性能测试来做到这一点,而不会对SO提出任何问题。