简易Java(15):Java中equals()
与hashCode()
之间的联系
Java的最基本的父类java.lang.Object
中有两个非常重要的方法定义:
public boolean equals(Object obj) public int hashCode()
实践证明,正确理解这两个方法非常重要,尤其是向Map
中添加用户自定义的对象时。即便如此,甚至有些高级开发人员有时很很难说清楚它们到底应该怎么用。在这篇文章里,我将先展示几个常见的错误例子,然后再解释这两个方法如何才能正确地配合。
1、一个常见错误
在下面的代码中,展示了一个常见的错误。
package com.diguage.books.simplejava.ar15; import java.util.HashMap; import java.util.Map; /** * equals()方法的错误示例 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-09 21:40 */ public class Apple { private String color; public Apple(String color) { this.color = color; } @Override public boolean equals(Object obj) { if (!(obj instanceof Apple)) { return false; } if (this == obj) { return true; } return this.color.equals(((Apple) obj).color); } public static void main(String[] args) { Apple a1 = new Apple("green"); Apple a2 = new Apple("red"); //hashMap stores apple type and its quantity Map<Apple, Integer> m = new HashMap<Apple, Integer>(); m.put(a1, 10); m.put(a2, 20); System.out.println(m.get(new Apple("green"))); } }
在这里例子里,一个绿色苹果的对象被成功存储到HashMap
中。但是,从这个Map
中取出这个苹果时,这个苹果对象却找不到了。上面的程序输出为null
。但是,在通过调试器,我们非常确定这个对象就存储在HashMap
中。如下图:
2、hashCode()
造成的问题
这个问题是由于没有覆盖hashCode()
。equals()
和hashCode()
之间的契约是这样的:1)如果两个对象是相等的,那么它们必须有相同的哈希值(Hash Code);2)如果两个对象有相同的哈希值,那么它们未必一定相等。
Map
的一种隐含意义就是比线性搜索能更快地找到对象。使用经过哈希计算过的键值去定位对象需要两步处理。在Map
内部,对象被存在数组中的数组中。第一层数组的下标就是键的hashCode()
返回值。搜索第二层数组是使用线性搜索,通过使用equals()
来判断对象是否被找到。
D瓜哥注
这里对
java.util.HashMap
内部实现的描述并不是十分准确。根据源代码显示,第一层确实是数组,如果有Key
的哈希值一样,即哈希冲突,则将其存为一个链表。感兴趣的小伙伴可以自己查看一下HashCode
的源代码。
hashCode()
在Object
类中的默认实现是,针对不同的对象,返回不同的整数值。因此,在上述例子中,不同的对象(即使是同一类型)有不同的哈希值。
哈希值就像一系列用于存储的仓库,不同的物品存放在不同的仓库里。相比将物品存放到同一个仓库,存放到不同地方会更加高效。因此,使用平均分散的哈希值是一个非常好的实践。(这不是本文重点,不再展开讲。)
解决办法就是在类中覆盖hashCode()
方法。针对这个示例,我使用color
字符串的长度即可。代码如下:
D瓜哥注
这不是好的实现方式,但是仅仅是针对本例已经足矣。
/** * 本例子中hashCode() 方法的的正确使用 * <p/> * Coder:D瓜哥,http://www.diguage.com/ * <p/> * Date: 2014-11-09 21:40 */ public int hashCode() { return this.color.length(); }
《Simple Java》是一本讲解Java面试题的书。讲解也有不少独特之处,为了面试,《简易Java》走起!
原文链接:equals()与
hashCode()
之间的联系">https://wordpress.diguage.com/archives/122.html版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。