学习、分享

站在巨人的肩膀上

JAVA 中的 HashCode 与 Equals

hashCode 与 equals

二者都是Object默认的方法,默认情况下,equals()比较两个对象的内存地址是否相等。hashCode()用于Hash表快速查找对象,hashCode()也由对象内存地址决定(值不是内存地址)。以下程序查看对象的内存地址以及hashCode。

equals 用于判断对象是否相同,那 hashCode 的作用是什么?

hashCode 主要用于 Hash 表,我们知道 Hash 表查询速度很快,其采用“数组+链表”的存储方式,通过特定的哈希函数,将所要存储的数据映射到对应的地址,下次访问直接计算得到内存地址取值,当多个存储对象出现哈希冲突时,采用拉链法,从该位置建立链表,当采用的哈希函数适当时,数据能够均匀分布,查询速度接近O(1)。

不难看出,hashCode 用于第一步寻址,直接找到目标或链表头结点,而 equals 顺着链表找到目标。

重写 hashCode 与 equals

为什么要重写?因为很多时候我们会遇到这种场景:

分析一下,为什么输出是 null, 因为通过new 创建的新对象与 HashMap 中的对象 hashCode() 不一致,equals() 更不一致,在第一步查找定位就失败了。

因此,我们必须重写上述两个方法, 重写的代码很繁琐,所幸 Ideaj 和 Eclipse 都可以自动快速帮助我们生成。Idea 下通过 Alt + Insert 可以调出自动生成菜单。

这里的 hashCode() 默认使用了字符串的哈希值计算方法,哈希函数影响查询的效率,我们也能自定义哈希函数,例如经典的取模法,以下是一个取模法的例子。

在HashSet.add(b)时,先查找是否有对应的hashCode,再使用equals()比较对象,如果有同一对象存在,则不执行add操作。由于没有重写 equals() 方法,HashSet 添加了两个对象,其 hashCode 均为 1。

总结

hashCode() 和 equals() 是哈希表存储和查询对象的重要依据,两者必须同时重写。

不同对象 equals() => false,但 hashCode 可以相同。

本文参考:

Java中hashCode的作用——冯立彬
HashMap实现原理及源码分析

点赞
  1. anderamirk.org说道:

    Pretty nice post. I just stumbled upon your blog and wanted
    to say that I've truly enjoyed browsing your blog
    posts. In any case I'll be subscribing to your rss feed and I hope you write again soon!

  2. Howdy would you mind sharing which blog platform you're working
    with? I'm planning to start my own blog soon but I'm having a hard time selecting between BlogEngine/Wordpress/B2evolution and Drupal.

    The reason I ask is because your layout seems different then most blogs and I'm looking for something completely unique.
    P.S My apologies for getting off-topic but I had to ask!

    1. chiyiw说道:

      I'm using WordPress with the theme 'Kratos'. You can find it on https://github.com/Vtrois/Kratos.

发表评论

电子邮件地址不会被公开。 必填项已用*标注