当前位置: 首页 > 编程语言 > C#

好的GetHashCode()OverridesListofFooObjectsRespectingOrder分享

时间:2023-04-10 21:31:13 C#

好的GetHashCode()OverridesListofFooObjectsRespectingOrder它们是相等的。因此,必须实现GetHashCode。问题在于,对列表中的每个元素进行异或运算,无论顺序如何,都会为任何包含所有且仅包含相同元素的列表返回相同的哈希码。就工作而言,这很好,但会导致许多冲突,这会减慢检索速度等。对于依赖于顺序的对象列表,什么是好的、快速的GetHashCode方法?我这样做的方式与您通常组合哈希码的方式相同-加法和乘法:publicoverrideintGetHashCode(){unchecked{inthash=19;foreach(varfooinfoos){hash=hash*31+foo.GetHashCode();}返回散列;(请注意,在任何描述的哈希表中使用此键后,不应向列表中添加任何内容,因为哈希值会发生变化。这也假设没有空条目——如果可能,您需要考虑到这一点。)首先,仔细检查您是否需要哈希码。你打算将这些列表放入哈希映射结构(例如字典、哈希集等)中吗?如果没有,那就算了。现在,假设您的意思是EnumerableObject已经覆盖了Equals(object)(因此希望也因此实现IEquatable),那么这确实是必要的。您希望在速度与位分配之间取得平衡。一个好的起点是mult+add或shift+xor,例如:publicoverrideintGetHashCode(){intres=0x2D2816FE;foreach(variteminthis){res=res*31+(item==null?0:item.GetHashCode());}返回资源;}(假设您使用item.Equals()进行序列相等性比较,如果您使用IEqualityComparer则需要调用其哈希码)。从那里我们可以优化。如果不允许null项,则删除null检查(请注意,如果确实找到null,这将使代码抛出)。如果非常大的列表很常见,我们需要减少检查次数,同时尽量不引起大量冲突。比较以下不同的实现:publicoverrideintGetHashCode(){intres=0x2D2816FE;intmax=Math.Min(Count,16);for(inti=0,i!=max;++i){varitem=this[i];res=res*31+(item==null?0:item.GetHashCode());}返回资源;}publicoverrideintGetHashCode(){intres=0x2D2816FE;intmin=Math.Max(-1,Count-16);for(inti=Count-1,i!=min;--i){varitem=this[i];res=res*31+(item==null?0:item.GetHashCode());}返回资源;}publicoverrideintGetHashCode(){intres=0x2D2816FE;int步骤=计数/16+1;for(inti=0,i这些中的每一个都限制了所有检查的项目总数,导致执行速度更快,但代价是哈希质量较差。哪个(如果有的话)最好取决于集合是否具有相同的开头或同一端的可能性更大。更改16以上的数字将调整平衡;更小但更快,但具有更高的哈希质量和更低的哈希冲突风险。编辑:现在你可以使用我对SpookyHashv.2的实现:Update(item.GetHashCode());//或item的相关feeds等returnhasher.Final().GetHashCode();这将创建比mult+add或shift+xor更好的分布,同时也非常快(特别是在64位进程中,因为算法为此优化,尽管它也适用于32位)。.GetHashCode()方法通常只返回基于对象引用(指针地址)的散列。这是因为计算可枚举列表中每个项目的哈希码可能非常耗时。我不想覆盖现有的行为,而是使用扩展方法并且只在hashcode确定性确定的地方使用它:内容,如果它对你有用并且你需要了解更多关于C#的学习教程,我希望你会更多关注---publicstaticclassEnumerableExtensions{publicstaticintGetSequenceHashCode(thisIEnumerablelist){if(list==null)return0;constintseedValue=0x2D2816FE;constintprimeNumber=397;返回list.Aggregate(seedValue,(current,item)=>(current*primeNumber)+(Equals(item,default(TItem))?0:item.GetHashCode()));}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: