重写 GetHashCode 的最佳算法是什么?

2023-11-27

在 .NET 中,GetHashCode method在 .NET 基类库的很多地方都使用了它。正确实现它对于在集合中快速查找项目或确定相等性时尤其重要。

是否有关于如何实施的标准算法或最佳实践GetHashCode对于我的自定义课程,这样我就不会降低性能?


我通常会采用 Josh Bloch 中给出的实现方式fabulous 有效的Java。它速度很快,并且创建了一个相当好的哈希值,不太可能导致冲突。选择两个不同的素数,例如17 和 23,并执行以下操作:

public override int GetHashCode()
{
    unchecked // Overflow is fine, just wrap
    {
        int hash = 17;
        // Suitable nullity checks etc, of course :)
        hash = hash * 23 + field1.GetHashCode();
        hash = hash * 23 + field2.GetHashCode();
        hash = hash * 23 + field3.GetHashCode();
        return hash;
    }
}

正如评论中所述,您可能会发现最好选择一个大素数来相乘。显然 486187739 很好......虽然我见过的大多数小数字的例子都倾向于使用素数,但至少有类似的算法经常使用非素数。在不完全-FNV稍后的例子,例如,我使用了显然运行良好的数字 - 但初始值不是素数。 (乘法常数is不过。我不太清楚这有多重要。)

这比通常的做法要好XOR计算哈希码有两个主要原因。假设我们有一个类型有两个int fields:

XorHash(x, x) == XorHash(y, y) == 0 for all x, y
XorHash(x, y) == XorHash(y, x) for all x, y

顺便说一句,早期的算法是 C# 编译器当前用于匿名类型的算法。

这一页提供了相当多的选择。我认为对于大多数情况,上述内容“足够好”,并且非常容易记住和正确执行。这FNV替代方案同样简单,但使用不同的常量和XOR代替ADD作为组合操作。它看起来某物像下面的代码一样,但是普通的 FNV 算法对单个字节进行操作,因此这需要修改为每个字节执行一次迭代,而不是每个 32 位哈希值。 FNV 还设计用于可变长度的数据,而我们在这里使用它的方式始终针对相同数量的字段值。对此答案的评论表明,这里的代码实际上并不像上面的加法方法那样有效(在测试的示例案例中)。

// Note: Not quite FNV!
public override int GetHashCode()
{
    unchecked // Overflow is fine, just wrap
    {
        int hash = (int) 2166136261;
        // Suitable nullity checks etc, of course :)
        hash = (hash * 16777619) ^ field1.GetHashCode();
        hash = (hash * 16777619) ^ field2.GetHashCode();
        hash = (hash * 16777619) ^ field3.GetHashCode();
        return hash;
    }
}

请注意,需要注意的一件事是,理想情况下,您应该防止将相等敏感(因此对哈希码敏感)状态添加到依赖于哈希码的集合后发生更改。

根据文档:

您可以覆盖不可变引用类型的 GetHashCode。一般来说,对于可变引用类型,仅在以下情况下才应重写 GetHashCode:

  • 您可以从不可变的字段计算哈希码;或者
  • 当可变对象包含在依赖于其哈希码的集合中时,您可以确保该对象的哈希码不会更改。

链接到FNV文章已损坏,但这是互联网档案馆中的副本:永远困惑 - 哈希的艺术

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重写 GetHashCode 的最佳算法是什么? 的相关文章

  • 访问 XAML 中的静态字段

    如何在 xaml 中引用类的静态属性 换句话说 我想做这样的事情 Class BaseThingy public static readonly Style BaseStyle
  • 在 C# 中将 ANSI (Windows 1252) 转换为 UTF8

    I ve 之前问过这个 https stackoverflow com q 4351985 398713之前在 Stack Overflow 上以一种迂回的方式 这次想把它做好 如何将 ANSI 代码页 1252 转换为 UTF 8 同时保
  • 用 C# 编写插件或插件框架

    我正在用 C 编写一个 Addin 框架 我想知道如何使 Addin 可以卸载而无需重新启动应用程序 我听说过 AppDomains 但是它们是如何工作的呢 外接程序是否可以添加可扩展性类并通过接口在主应用程序域中调用 并且仍然可卸载并调用
  • 如何在VS2017中从.net项目引用netstandard项目?

    我有一个 netstandard2 0 项目 用于与第三方 Web 服务交互 我需要在同一解决方案中引用旧的 net 4 6 2 项目中的该项目 但是当我这样做时 我会收到一堆关于需要引用我定义的类型的错误 例如 我将调用 netstand
  • 如何判断应用程序是否是Web应用程序

    在 Windows 服务和 Web 应用程序中运行的核心程序集中 我需要存储每个用户会话的信息 该服务将具有单个用户会话 并且 Web 应用程序使用 HttpContext Current 我想配置在核心程序集中使用哪种方法 约定优于配置
  • 面向对象的铸造错误[重复]

    这个问题在这里已经有答案了 将派生类强制转换为基类 我有一个通用的基本抽象类 继承自 IComparable 其定义如下 public abstract class BaseClass
  • MS Teams 应用程序:访问此应用程序时出现问题

    The users on MS Teams desktop reported multiple issues with our MS Teams app They see the following error on MS Teams De
  • 任务并行库周围是否有一个接口包装器,以便我可以将其交换用于单元测试?

    I asked 这个问题 https stackoverflow com questions 3362734 unit testing concurrent software what do you do不久以前 我现在知道这是一个坏主意
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 应用对数来导航树

    我曾经知道一种使用对数从树的一片叶子移动到树的下一个 有序 叶子的方法 我认为它涉及获取 当前 叶子的位置值 排名 并将其用作从根向下到新目标叶子的新遍历的种子 一直使用对数函数测试来确定是否沿着右或左节点向下到达叶子 我已经不记得如何运用
  • 如何在 C# 中使用 Outlook MAPI 打开 .eml 文件?

    我有一个 C 应用程序 可以读取 msg 文件并提取正文和附件 但是当我尝试加载 eml 文件时 应用程序崩溃了 我正在加载这样的文件 MailItem mailItem MailItem outlookApp CreateItemFrom
  • 如何从进程开始捕获所有应用程序/窗口消息? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我试图弄清楚如何捕获进程 窗口的所有窗口消息 从它在 c 中启动时开始 该过程不是我自己的 所以我需要使用某种钩子 我的目标是开始实时
  • DLL 中的 GUID (.Net)

    我在这方面不是很有经验 所以我有几个问题 首先 所有 Net 创建的 DLL 是否都有自己的 GUID 如果没有 我的问题是如何获得一个并将其与 DLL 关联 那么问题是 我如何获得该 dll 的 GUID 即 给定 DLL 路径 c so
  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • 并行化斐波那契序列生成器

    我正在学习并行化 在一项练习中 我得到了一些我应该提高性能的算法 其中之一是斐波那契数列生成器 array 0 0 array 1 1 for q 2 q lt MAX q array q array q 1 array q 2 我怀疑 这
  • C# 中的 C/C++ 代码编译器

    在 C 中 我可以使用下面的代码编译 VB 和 C 代码 但无法编译 C C 代码 有什么办法可以做到这一点吗 C 编译器 public void Compile string ToCompile string Result null st
  • 在哪里可以下载没有 Visual Studio 2010 的 C# 4.0 编译器?

    我知道 CTP VS 2010 映像 但我可以只下载 NET Framework 4 0 和 C 编译器吗 AFAIK VS 2010 CTP 仅作为 VM 映像提供 我不相信 Microsoft 发布了 VS 的安装程序 其中一个绝对不适
  • 优先连接,Matlab 中的复杂网络

    大家好 我现在正在 MATLAB 中研究优先附件模型 在理解以下内容时遇到一些困难 假设我一开始有 4 个节点 连接如下 time 0 1 lt gt 2 3 lt gt 4 在下一个时间步骤中 我添加一个节点和 4 个连接 然后添加另一个
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可
  • 调试VS 2005提示“操作不支持”

    我一直在调试 VS 2005 并将 启动外部程序 设置为 C Program Files Microsoft Visual Studio 10 0 Common7 IDE devenv exe 但按 F5 后出现此错误 尝试运行项目时出错

随机推荐

  • iphone sdk 应用程序的最佳正则表达式库? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我对 iPhone SDK 中提供的正则表达式库感到困惑 例如 RegexLite 看起来需要一个动态链接 据我了解 这对于 iPhone 上的 S
  • powershell - 变量引用无效。 “:”后面没有有效的变量名字符

    我正在尝试做的是让radar在将Web客户端请求的电影移动到persons文件夹后删除它 因此如果默认路径是D Movies 那么只需记录它 如果它去了除D之外的任何其他地方 Movies 然后它会将其从客户端中删除 寻求一些指导 因为我对
  • 在 Visual Studio 中删除匹配的大括号

    在 Visual Studio 中 我可以使用以下命令从 到左大括号 右大括号跳转Control 捷径 是否有一个快捷方式可以让我一次删除两个大括号 也许使用宏 扩展名 e g foo 1 bar 2 当我位于第一个左大括号时 我想删除它及
  • iOS 企业部署/到期

    我们最近注册了一个 iOS 企业帐户 用于内部应用程序分发 搜索论坛发现了两件事我想得到确认 1 企业分销证书有效期为3年 这是否意味着我们需要使用新证书重新构建应用程序 否则它将无法运行 2 供应配置文件将在 1 年后到期 这是否意味着我
  • Android Studio - TextView 未显示在设计视图布局中

    我是尝试 Android 应用程序的新手 我开始遵循在线教程 https developer android com training basics firstapp building ui 但是在添加新的 TextView 时有点沮丧 根
  • “User.IsInRole”中的多个角色[重复]

    这个问题在这里已经有答案了 我的页面上有 3 个角色 因此我想访问具有两个角色的链接 我尝试这样的事情 if User IsInRole Admin User my code Or this if User IsInRole Admin U
  • 生成非均匀分布的随机数

    JavaScript 的Math random 返回具有 均匀 分布的伪随机数 我需要生成一个范围 0 1 内偏向任意一侧的随机数 意思是 获得更多 0 或 1 旁边的数字的机会更大 理想情况下 我想要一个参数来设置这条曲线 我以为我能做到
  • “for”循环中是否允许多个条件?

    以下代码运行时不会给出任何错误或警告 include
  • 当我运行 hibernate 5 时,弹出 Microsoft SQL 变体类型错误

    每当我运行 hibernate 5 时 我都会看到以下错误 ERROR Could not fetch the SequenceInformation from the database com microsoft sqlserver jd
  • 如何使用 .htaccess 将错误 404 重定向到主页?

    您好 如何将错误 404 重定向到带有 htaccess 的主页 例子 site com如果写site com some site notforund而不是 404 将我们重定向到主页 示例2 虐待狂 pl如果写Sadistic pl so
  • declarativeNetRequest更新规则

    正如我正在尝试更新的文档中所述declarativeNetRequestChrome 扩展的规则 来自文档 更新动态规则 chrome declarativeNetRequest updateDynamicRules 整数ruleIdsTo
  • sed 用捕获组替换行

    sed 是否可以用正则表达式中的捕获组替换行 我有这个正则表达式 请注意这是固定的 我无法更改它 simple sample 这就是我要的 This is just a simple sample line with some text 改
  • 单个更新查询需要事务吗?

    我在 InnoDB 表上有一个 mysql 查询 如下所示 UPDATE items SET qty qty 5 WHERE item id 1234 LIMIT 1 我需要为此使用交易吗 不使用交易会发生什么不良后果吗 不会发生什么严重的
  • MySQL VARCHAR 长度和 UTF-8

    在 MySQL 中 如果我创建一个新的VARCHAR 32 UTF 8 表中的字段是否意味着我可以在该字段中存储 32 个字节的数据或 32 个字符 多字节 这个答案出现在我的谷歌搜索结果的顶部 但不正确 The 困惑可能是由于测试的MyS
  • 如何使用 Lua 从 zip 文件中提取文件?

    如何使用 Lua 提取文件 更新 我现在有以下代码 但每次到达函数末尾时都会崩溃 但它成功提取所有文件并将它们放在正确的位置 require zip function ExtractZipAndCopyFiles zipPath zipFi
  • 如果满足某些条件,则合并列表的元素

    如何组合列表的元素if满足某些条件 我看过有关组合列表元素的帖子 但没有看到某些条件 假设我有一个包含单词列表的列表 words this that riff raff hip hop flip flop humpty dumpty pro
  • 如何在 cURL 二进制 get 请求中获取文件的长度而不下载文件

    我想在一些 C 代码中创建一个 cURL 请求 该请求将在不下载文件的情况下获取服务器中文件的长度 为此 我使用一些 cURL 选项来告诉我只需要请求响应中的标头 然后检查响应以获取文件长度 我正在设置以下请求选项 curl easy se
  • 将 IEnumerable 拆分为固定大小的块(返回 IEnumerable> ,其中内部序列具有固定长度)[重复]

    这个问题在这里已经有答案了 我想采取IEnumerable
  • 在单次迭代中对两个数组求和

    我想将数字数组的每个值与其在不同数字数组中的对应值相加 并且我想在不循环遍历每个单独的值的情况下执行此操作 So var array1 1 2 3 4 var array2 5 6 7 8 var sum 6 8 10 12 我很想一下子做
  • 重写 GetHashCode 的最佳算法是什么?

    在 NET 中 GetHashCode method在 NET 基类库的很多地方都使用了它 正确实现它对于在集合中快速查找项目或确定相等性时尤其重要 是否有关于如何实施的标准算法或最佳实践GetHashCode对于我的自定义课程 这样我就不