关于 hashCode() 你需要了解的 3 件事

  1. 永远不要把哈希码误用作一个key

 

你可能会反对,不像打印机的类型例子,在 Java 中,有 4,294,967,296 的空间(2^32 个可能的整型值)。40亿的插槽,发生冲突似乎是极不可能的对吗?

事实证明它不是不太可能。这是令人惊讶的冲突:请想象一下在一个房间里有 23 个随机的人。你觉得两个人是同一天生日的几率有多大 ?很低,因为一年有 365 天吗?事实上,几率是 50% 左右!50 个人是保守的估计。这个现象称为生日悖论。应用到哈希码,这意味着在 77163 个不同的对象中,有 50% 的可能性发生冲突–假设你有一个理想的哈希的函数,均匀地把对象分布在所有可用的空间里面。

 

例如:

安然公司的电子邮件集包含 520,924 封电子邮件。计算电子邮件内容字符串的哈希码时,我发现 50 对(甚至是 2 个三元组)不同的电子邮件有着相同的哈希码。对于五十万个字符串,这是一个很好的结果。但是这里的信息是:如果你有很多数据元素,冲突就会发生。如果你正在使用哈希码作为 key,你不会立即注意到你的错误。但是少数人会收到错误的邮件。

、哈希码可变

最后,在哈希码的契约中,有一个很重要的细节是相当让人吃惊的:hashCode 并不保证在不同的应用执行中得到相同的结果。让我们看一看 Java 文档:

 

在一次 Java 应用的执行中,对于同一个对象,hashCode 方法必须始终返回相同的整数,但这整数不反映对象是否被修改(equals 比较)的信息。同一个应用的不同执行,该整数不必保持一致。

 

事实上,这是不常见的,一些类库中的类甚至指定它们用于计算哈希码的精确公式(例如字符串)。对于这些类,哈希码总是会相同。虽然大部分的哈希码的实现提供稳定的值,但你不能依赖于这一点。正如这篇文章指出的,有些类库在不同进程中会返回不同的哈希值,这有的时候会让人困惑。谷歌的 Protocol Buffers 就是一个例子。

 

因此,你不应该在分布式应用程序中使用哈希码。一个远程对象可能与本地对象有不同的哈希码,即使这两个对象是相等的。

 

  1. 在分布式应用中不要使用哈希码

 

此外,你应该意识到从一个版本到另一个版本哈希码的功能实现可能会更改。因此您的代码不应该依赖于任何特定的哈希码值。例如,你不应该使用哈希码来持久化状态。下次你运行程序的时候,“相同”对象的哈希码可能不同。

最好的建议可能是:完全不使用哈希码,除非你自己创造了基于哈希的算法。

 

一种替代方法:SHA1

你可能知道加密的哈希码 SHA1 有时被用来标识对象(例如,git这样做)。这也是不安全吗?不。SHA1 使用 160 位密钥,这使得冲突几乎是不可能的。即使有很多对象,在这个空间发生冲突的几率远远低于一颗流星撞到你正在执行程序的电脑的几率。这篇文章对冲突的概率作了很好的概述。

 

关于哈希码应该还有其他可谈的,但这些看起来是最重要的。如果我有什么遗漏,欢迎告诉我。

 

 


上一篇:
下一篇:
关于尚硅谷
教育理念
名师团队
学员心声
资源下载
视频下载
资料下载
工具下载
加入我们
招聘岗位
岗位介绍
招贤纳师
联系我们
全国统一咨询电话:010-56253825
地址:北京市昌平区宏福科技园综合楼6层(北京校区)

深圳市宝安区西部硅谷大厦B座C区一层(深圳校区)

上海市松江区谷阳北路166号大江商厦6层(上海校区)

武汉市东湖高新开发区东湖网谷(武汉校区)