java~重写hashcode时为什么要乘以31

news/2024/12/25 13:07:30/文章来源:https://www.cnblogs.com/lori/p/18630150

在Java中,重写hashCode()方法时常常会使用31作为乘数,这是因为31具有一些独特的数学性质,使其成为一个优秀的选择。以下是几个原因:

1. 奇质数的特性

31是一个奇数和质数,这意味着它能有效地减少哈希冲突的概率。使用质数作为乘数可以帮助分散哈希值,从而提高哈希表的性能。

2. 位运算效率

在计算机中,乘以31可以通过位运算来优化:

  • x * 31可以用 (x << 5) - x 来替代,其中<<表示左移操作。这种方式比直接乘法更加高效,因为位移操作通常比乘法快得多。

3. 良好的分布性

经过实践证明,31可以提供良好的哈希值分布,适用于字符串等对象的哈希计算。它能够有效地将不同的输入映射到不同的哈希值上,减少了碰撞的可能性。

示例代码

下面是一个简单的示例,展示如何在hashCode()方法中使用31:

@Override
public int hashCode() {int result = 17; // 一个非零的初始值result = 31 * result + (field1 != null ? field1.hashCode() : 0);result = 31 * result + (field2 != null ? field2.hashCode() : 0);return result;
}

在这个例子中,field1field2的哈希值被乘以31并累加到结果中,从而生成一个组合的哈希值。

总结

使用31作为乘数在hashCode()重写中是为了提高哈希函数的性能和分布性。它结合了数学上的优雅与计算上的高效,是Java开发者的常见做法。

质数提高哈希分散性

在哈希函数中,使用质数(如 31、37、53 等)进行乘法运算是一个常见的实践,这样做可以提高哈希值的分散性,减少哈希冲突。下面是对这一现象的详细解释:

1. 哈希冲突的概念

哈希冲突发生在不同的输入数据被映射到同一个哈希值时。这种情况会导致哈希表性能下降,因为在查找、插入或删除操作时需要处理这些冲突。

2. 为什么使用质数?

a. 数学性质

  • 质数的特性:质数是只能被 1 和它自身整除的自然数。这个特性使得它们在数学上具有良好的分布性。
  • 避免重复模式:使用质数可以有效地打破输入数据之间的规律性和重复模式,从而增加哈希值的随机性。例如,如果我们总是用偶数来计算哈希值,可能会导致某些输入数据产生相似的哈希结果,而质数的使用可以防止这种情况。

b. 增强混合效果

  • 乘法的影响:当我们将当前哈希值与质数相乘并加上新的元素的哈希值时,质数有助于在生成的新哈希值中引入更多的信息。这样可以有效地“混合”之前的哈希值和新添加的值。

  • 例如

    result = prime * result + newValueHash;
    

    在这个公式中,result 是之前计算得到的哈希值,newValueHash 是新加入元素的哈希值。通过乘以质数 prime,我们确保了即使 newValueHash 的值相似,它们也不会简单地叠加在一起,从而减少冲突的概率。

3. 位运算优化

  • 计算效率:在 Java 中,选择 31 作为质数的一个原因是,它可以通过位移运算进行优化。具体来说,乘以 31 可以通过以下方式实现:
    result = (result << 5) - result; // 相当于 result * 31
    
    这里的 << 5 表示左移 5 位,相当于乘以 32,然后再减去原值 result,达到乘以 31 的效果。这样的操作比直接乘法更高效。

4. 实际应用中的效果

通过使用质数来计算哈希值,可以显著提高哈希函数的分散性,使得不同的输入能够产生更加均匀的哈希分布。这对于实现高效的哈希表(如 HashMapHashSet)至关重要,因为它能减少冲突、提高查找速度,并优化内存使用。

总结

  • 使用质数(如 31)在哈希函数中可以提高哈希值的分散性,减少哈希冲突。
  • 质数的数学特性和乘法带来的混合效果有助于生成更随机的哈希值。
  • 通过位运算优化乘法运算,可以提高计算效率。

因此,在设计哈希函数时,使用质数是一种有效的策略,以确保哈希表结构的性能和效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/858608.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据误删?别怕!COS防误删攻略请查收

在云存储领域,数据的安全性始终是悬在头顶的达摩克利斯之剑。长期以来,腾讯云对象存储服务(COS)一直致力于数据安全的探索和实践,以保障数据的安全性和完整性。对象存储COS准备了一份防误删攻略给大家: 背景与意义在云存储领域,数据的安全性始终是悬在头顶的达摩克利斯之…

【日记】拼好了衣架!(524 字)

正文今早不小心把闹钟给关了,继 7:50 闹钟响了之后,下一次睁眼就是 8:28 了。吓得一哆嗦,穿衣服换鞋的速度起飞。到一楼,正好 8:30。还好行长没来(小声。昨天晚上,朝哥给我说他伤好得差不多了,可以开始考虑上课了。我一直在等他说出这句话。暑假班他受伤,完事儿之后我受…

【原创】解决ncnn yolov11 乱框,输出维度出错,无框问题

Abstract 解决:ncnn yolov11 乱框,输出维度出错,无框问题 Solution: ncnn yolov11 has random boxes, incorrect output dimensions, and no boxes 0x00: model export 首先是模型转换问题 最开始,我是用python的ultralytics导出为onnx格式文件(.onnx),这个文件在python的…

polarctf-crypto中等难度wp整理(截止至2024.12)

二进制一个音频文件,听了,不是摩斯电码看了wp,原来是拨号 考察:DTMF拨号音识别 使用dtmf2num这个工具解析这个音频二进制1和0 但是不是,它是01字符变形成摩斯密码,把0替换成.,把1替换成-,把*替换成空格。 得到一组摩斯电码,然后去解即可还要小写md5加密,服了这个老六…

杭州数据恢复之某公司经理的三星移动硬盘摔坏了盘片划伤二次开盘

这是一块老款三星Samsung使用mini USB接口的500G移动硬盘,采用了一体式电路板,型号是HM502JX。硬盘是用户不小心摔坏了,接电脑不识别而且有异响,先送修到百脑汇电脑城某家数据恢复中心进行开盘修复,但被告知盘片有划伤无法恢复数据。很巧用户公司里的一名员工曾经在我们这…

第十七次作业

1、安装最新版phpstudy集成工具并创建一个网站,编写php代码输出网站信息(phpinfo)2、安装vscode,并安装php开发插件、汉化插件、xdebug等插件 中⽂语⾔包安装php调试插件配置Open PHP/HTML/JS In Browser插件3、配置phpstudy集成工具xdebug扩展,并使用vscode对php代码进行…

dataezse接入zabbix监控

常用查询 目录常用查询zabbix 常用库表说明主机资源监控主机资源监控(纯值)oracle状态监控CPU top10DISK TOP 10Memory TOP 10SPACE USERD TOP 10问题告警级别分布问题列表null问题主机组正常主机总数主机问题排行 zabbix 常用库表说明 https://www.cnblogs.com/yaoyaojcy/p/…

MySQL 千万 级数据量根据(索引)优化 查询 速度

MySQL 千万 级数据量根据(索引)优化 查询 速度| Id | Title | DateAdded | SourceUrl | PostType | Body | BlogId | Description | DateUpdated | IsMarkdown | EntryName | CreatedTime | IsActive | AutoDesc | AccessPermission | | -------------| -------------| -----…

kafka中文教程

kafka中文教程| Id | Title | DateAdded | SourceUrl | PostType | Body | BlogId | Description | DateUpdated | IsMarkdown | EntryName | CreatedTime | IsActive | AutoDesc | AccessPermission | | -------------| -------------| -------------| -------------| -------…

银河麒麟桌面操作系统 使用root登录桌面端

麒麟 V10 桌面操作系统使用 root 登录 - 乔京飞 - 博客园 一、允许使用 root 用户登录 麒麟 V10 桌面操作系统安装过程后(或者安装完成后),必须创建一个新用户才能使用。很多目录中的文件,只能看不能改,甚至连创建一个新文件都不行。在终端执行命令,需要频繁的使用 sudo …

oracle exp 无法导出空表

oracle exp 无法导出空表| Id | Title | DateAdded | SourceUrl | PostType | Body | BlogId | Description | DateUpdated | IsMarkdown | EntryName | CreatedTime | IsActive | AutoDesc | AccessPermission | | -------------| -------------| -------------| ------------…