Java的超类java.lang.Object定义了两个非常重要的方法:
public boolean equals(Object obj) public int hashCode()理解这两方法之间的区别联系是非常重要的,特别是当用户自定义的对象被添加到Map中。然而,即使高级开发人员有时无法弄清楚他们应该如何正确使用。在这篇文章中,我会先给大家看一个常见的错误的例子,然后解释如何的equals()和hashCode()之间的区别联系。
1.一个常见的??错误
请看下面的例子:
import java.util.HashMap; public class Apple { private String color; public Apple(String color) { this.color = color; } public boolean equals(Object obj) { if (!(obj instanceof Apple)) return false; if (obj == this) 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 HashMap<Apple, Integer> m = new HashMap<Apple, Integer>(); m.put(a1, 10); m.put(a2, 20); System.out.println(m.get(new Apple("green"))); } }
在这个例子中,一个color属性为“green”的Apple对象被成功地存储在一个HashMap中,但是当Map被要求获取该对象时,结果发现Apple对象没有找到。上面的程序在控制台打印为null。但是,我们可以肯定的是,通过在调试器可以查看到对象确实是存储在HashMap中:
2.hashCode()造成的问题
这个问题是由未重写的方法hashCode()引起的。equals()和hasCode()之间的制约关系是:
1.如果两个对象是相等的,那么它们必须有相同的哈希码。
2.如果两个对象具有相同的哈希码,他们可能相等,可能不相等。
一个Map背后的想法是能够比线性搜索更快地定位到对象。使用散列键定位对象是一个两步的过程。Map内部存储对象是以数组的数组来存储。1.第一个数组的索引是hashCode()值的key。2.定位第二个数组(使用线性搜索找到的)是通过使用equal()来决定对象是否被找到?
hashCode()的默认实现是Object类为不同的对象返回不同的整数。因此,在上面的例子中,不同的对象(即使是相同类型的)具有不同的哈希码。
哈希码的存储就像车库中的序列一样,不同的车(对象)可以被存储在不同的车库中。如果你将不同的车(对象)放在不同的车库中而不是相同的车库中,那么会更有效。所以平均分配的hashCode值是一个很好的做法。(虽然不是这里的要点)
下面的例子是为一个类添加hashCode()方法的简单的解决方案,在这里,我只是用color字符串的长度作示范。
public int hashCode(){ return this.color.length(); }
相关文章:
- Java hashCode() and equals() Contract for the contains(Object o) Method of Set
- HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
- Yet Another “Java Passes By Reference or By Value”?
- What does a Java array look like in memory?