• 欢迎访问天天编码网站,Java技术、技术书单、开发工具,欢迎加入天天编码
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏天天编码吧
  • 我们的淘宝店铺已经开张了哦,传送门:https://shop145764801.taobao.com/

深入详解Java中的hashcode()与equals()方法

Java基础 tiantian 1723次浏览 1个评论 扫描二维码

Java中的超级父类 java.lang.Object 定义了两个重要方法:hashCode()与equals()方法。它们不仅被大量地直接使用,而且与集合容器,特别是与基于哈希机制的集合容器有着紧密的联系。本文中,我们首先提供一个常见的错误代码示例,接着分析错误原因,最后详细阐述 hashcode()equals() 方法之间的契约。

public boolean equals(Object obj);
public int hashCode();

常见错误

public class Cat {
private String color;

public Cat(String color) {
this.color = color;
}

@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof Cat)) return false;
if (obj == this) return true;
return this.color.equals(((Cat) obj).color);
}

public static void main(String[] args) {
Cat catA = new Cat(“white”);
Cat catB = new Cat(“black”);
HashMap<Cat, Integer> maps = new HashMap<>();
maps.put(catA, 10);
maps.put(catB, 20);
System.out.println(maps.get(new Cat(“white”)));
}
}

建议读者自己仔细思考得出答案后,再上级运行代码获得答案,正确的答案是打印了 null 。我们来分析一下该代码的结构,在该代码中,一个白色的猫对象被成功地存储在HashMap容器maps中,当尝试从该maps中查找该白色的猫对象时,却没有发现该对象。但是,我们可以通过使用IDE的debugger面板去检查HashMap容器maps,会发现白色的猫对象是已经存储在该maps中的。图片如下:

深入详解Java中的hashcode()与equals()方法

解决方案

造成错误的原因就在于Cat类只重写了equals()方法,没有相应地重写hashcode()方法。在Java中,一个类的equals()方法和hashCode()方法存在如下契约:

  1. 如果两个对象是相等的,那么他们的hashCode必须是相同的。
  2. 如果两个对象具有相同的hashCode,它们可以相等,也可以不相等。

总结起来就是一句话:如果重写了某类的equals()方法,那么肯定也需要重写该类的hashCode()方法,而且两个对象的equals()返回值相等的情况下,这两个对象的hashCode()方法的返回值也必须相等。

Java中的任何类,只有在遵守equals()方法与hashCode()方法之间的契约情况下,才能正确的作为各种基于哈希机制的集合容器的键,比如示例代码中的HashMap。通过使用哈希机制,HashMap的查找指定元素方法具有 O(1) 的时间复杂度,远远优于普通容器的线性时间复杂度。在HashMap中,通过哈希后的键去查找对应的值可以分为两个步骤。对于 Map 结构容器,我们可以看作成元素为数组的一个数组,元素在第一层数组的索引号就是其键的hashCode()值,在第二层数组中,元素使用其equals()来定位与判断该元素是否已存储。

对于Java中所有类的超级父类java.lang.Object而言,其hashCode()的默认实现是:对于不同的对象就返回不同的整型值。上述示例代码中,Cat类没有重写Object的hashCode()方法。所以,这条代码:

System.out.println(maps.get(new Cat(“white”)));

创建的Cat对象具有与catA不同的hashCode。

哈希机制的引入极大地提高了在集合容器中查找特定元素的速度。哈希码就像一系列的桶,不同哈希码的对象往往对应到不同的桶中。但是,不同的键值在经过哈希后,被对应到了同一个桶中,这取决于哈希函数的选取。好的哈希函数应该尽可能把不同键的值分配到不同的桶中。关于哈希机制的学习请参看本站的其他文章。

最后,我们给出一个上述问题代码的解决方案,把下面的代码添加到Cat类中即可。

@Override
public int hashCode() {
return this.color.hashCode();
}


天天编码 , 版权所有丨本文标题:深入详解Java中的hashcode()与equals()方法
转载请保留页面地址:http://www.tiantianbianma.com/java-hashcode-equals.html/
喜欢 (7)
支付宝[多谢打赏]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
(1)个小伙伴在吐槽
  1. 谢谢作者,很优秀的讲解
    匿名2017-10-15 18:29 回复 Windows 7 | Chrome 53.0.2785.104