Java源码学习-Object类的hashCode和equals方法

来源:互联网 发布:linux jenkins 配置 编辑:程序博客网 时间:2024/05/16 17:40

对于hashCode方法,可以按照Java SE 7 API中注释的那样来学习(https://docs.oracle.com/javase/7/docs/api)。

---------------------------------------------------------------------------------------------------------------------

疑问:学习Java的时候,经常听到有人说重写equals方法后需要重写hashCode方法,但是为什么呢?

看过《Java特种兵》后,发现其有一段描述比较清楚:hashCode的作用——它为了产生一个可以标识对象的数字。hashCode只能说是标识对象,因此在Hash算法中可以将对象相对离散开,这样就可以在查找数据的时候根据这个key快速地缩小数据的范围。但不能说hashCode值一定是唯一的,所以在Hash算法中定位到具体的链表后,需要进一步循环链表,然后通过equals()来对比Key的值是否是一样的。这时hashCode()与equals()似乎就成为“天生一对”。换句话说,一个是为了算法快速定位数据而存在的,一个是为了对比真实值而存在的。(本人注释:如果读者对于Hash算法原理以及其为什么能提高检索效率不是很清楚的话,建议网上搜搜数据结构或者算法的Hash算法方面的内容)


有了上面直观的介绍,我们还可以从Java SE 7(其他版本也可以) API 中得到上述内容的佐证。 

1.建立hashCode方法的目的:This method is supported for the benefit of hash tables such as provided by HashMap.(为了利用哈希表所带来的好处,就如同HashMap类中所提供的)


2.关于hashCode方法的一般性约定:The general contract of hashCode is :

   i.除非参与计算的对象属性值发生改变,对于某一对象的hashCode方法应始终返回相同哈希值。

   ii.如果两个对象通过equals方法判定为相同,则两个对象分别调用hashCode方法时应返回相同的哈希值。

   iii.如果两个对象通过equals方法判定为不相同,不强制要求两个对象分别调用hashCode方法时返回不同的值,即,允许equals比较后不相同,但是hashCode相同。但是如果equals判定不等,hashCode判定也不等的话,也许能提升哈希表的性能。


由Java API中信息可见,hashCode方法的存在就是为了能利用哈希表所带来的快速查找的特性。注意:由于存在上述第ii条约定,所以对于重写了equals方法的对象也应该重写hashCode方法。此处我们可以再直观的理解一下,假设我们自定义了一个类MyClass,这个类将来有可能会放到一个HashMap或者HashSet中,此时很自然的会用到HashMap或者HashSet中关于Hash算法相关特性,既然会用到Hash算法的相关特性,那自然会涉及到MyClass中的equals方法和hashCode方法;反过来,如果我们定义的这个类MyClass永远都用不到涉及Hash算法相关的特性类(例如:HashMap或者HashSet,那我们完全可以不重写hashCode方法)。



参考链接:

[1] Java SE 7 API, https://docs.oracle.com/javase/7/docs/api



0 0
原创粉丝点击