Java基础学习总结(12)——一哈希编码HashCode

本文从Java虚拟机角度介绍内存布局,指出Java虚拟机会用哈希编码记录对象位置,通过编码可快速确定对象所在位置。但Java本身对哈希编码的实现存在问题,不同内容对象可能有相同哈希编码,且概率较高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、哈希编码

  

  现在是站在JAVA虚拟机的角度来看内存里面的布局,站在JAVA虚拟机的角度,在内存里面有好多好多个对象,这里用椭圆来代表一个个对象。一个程序运行起来的时候,可能会有很多个对象在内存里面分配,那么对于JAVA虚拟机来说,它运行的时候需要找到这些对象的地址,这些对象的地址怎么找呢?JAVA虚拟机会用一张表记录每一个对象在什么位置上,而这张表一般是用哈希编码来记录,每一个对象都有自己独一无二的哈希编码,根据这个编码就可以找到相关的对象,也就是说,根据这个编码你可以独一无二地确定这个对象,并且可以非常快地确定这个对象所在的位置,可以简单这么理解哈希编码的作用。但是JAVA本身对哈希编码的实现有点问题,它有可能是两个对象,内容不同,但是它们的哈希编码居然有可能是一样的,而且这个概率非常高。

哈希编码是什么呢?它独一无二地代表了一个对象,并且通过哈希编码可以找到这个对象所在的位置。这就是哈希编码的作用。

转载于:https://my.oschina.net/zhanghaiyang/blog/593056

### Java 中 `hashCode` 方法的实现与用法 #### 定义和作用 在Java编程中,`hashCode()` 是个非常重要的方法,在涉及集合类(如 HashMap、HashSet 等)时尤为关键。此方法用于计算对象的哈希值,该值通常是个整数。当对象被存储到基于哈希表的数据结构中时,会利用这个哈希来决定对象应该放置的位置[^1]。 #### 如何正确实现 `hashCode` 为了确保 `hashCode` 的致性,应当遵循些基本原则: - **致性**:在个程序执行期间多次调用同个对象上的 `hashCode` 方法应返回相同的结果,前提是影响 `equals` 比较的对象字段未发生变化[^4]。 - **相等性映射至相同的哈希**:如果两个对象通过 `equals(Object)` 方法比较认为是相等,则这两个对象必须有相同的 `hashCode` 返回值;反之则不定成立——即不同对象可以拥有相同的哈希[^5]。 以下是几种常见的 `hashCode` 实现方式: ##### 使用标准库工具辅助生成 ###### Objects.hash() 这是最简单的方式之,适用于大多数情况下的快速开发需求。只需要传递给定属性作为参数即可获得合理的分布效果。 ```java @Override public int hashCode() { return Objects.hash(field1, field2); } ``` ##### 利用第三方框架简化编工作量 ###### Apache Commons Lang 库中的 HashCodeBuilder 提供了种更灵活的方法来自定义哈希函数的行为模式。 ```java import org.apache.commons.lang3.builder.HashCodeBuilder; // ... @Override public int hashCode() { return new HashCodeBuilder(17, 37). append(field1).append(field2).toHashCode(); } ``` ###### Google Guava 提供的支持 Guava也提供了类似的帮助器类来进行高效的哈希运算操作。 ```java import com.google.common.base.Objects; //... @Override public int hashCode(){ return Objects.hashCode(field1,field2); } ``` #### 和 equals 方法的关系 `hashCode` 和 `equals` 密切关联在起。具体来说就是,只要两个对象被认为是 “相等”的话 (`o1.equals(o2)==true`) ,那么它们所对应的 `hashCode` 结果也应该是样的(`o1.hashCode()==o2.hashCode()`) 。然而反过来并不定成立 —— 即使两者的 `hashCode` 相同也不代表二者就定是完全样的实体[^2]。 #### 注意事项和建议 - 对于不可变对象而言,可以在构造完成后立即缓存其 `hashCode` 值以提高性能效率; - 如果某个类没有合适的字段参与 `hashCode/equals` 计算的话,考虑继承自父类或者默认行为可能更为合适; - 当设计新的数据类型时务必同时覆盖这两个方法,并且要保证两者之间的致性和稳定性[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值