重写hashcode
学习:重写hashCode()方法的必要性
当一个类有可能会和其他类发生比较的时候,我们会重写equals方法,但大多数情况下,都忽略了重写hashCode方法。
这里说一下重写hashCode的必要性。
当我们使用HashSet或者HashMap的时候,在比对value|key是否存在时,会调用hashCode方法。
注意,hashSet的contains方法其实是依赖于HashMap的containsKey方法的。
我们来看下containsKey方法的实现:
public boolean containsKey(java.lang.Object paramObject)
{
return (getEntry(paramObject) != null);
}
final Entry<K, V> getEntry(java.lang.Object paramObject)
{
int i = (paramObject == null) ? 0 : hash(paramObject.hashCode());
Entry localEntry = this.table[indexFor(i, this.table.length)];
for (; localEntry != null;
localEntry = localEntry.next)
{
if (localEntry.hash == i) { java.lang.Object localObject;
if (((localObject = localEntry.key) == paramObject) || ((paramObject != null) && (paramObject.equals(localObject))))
{
return localEntry; } }
}
return null;
}
由上面代码即可知,hashCode是重要的判断依据,没有重写hashCode,equals表现相等的两个类,它们的hashCode并不相等。
所以会导致containsKey方法返回false,测试代码如下:
包含HashCode的类:
package hashset.and.hashcode;
public class ClassWithHashCode {
public int i;
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof ClassWithHashCode) {
ClassWithHashCode code = (ClassWithHashCode) o;
return code.i == i;
}
return false;
}
public int hashCode() {
return i * 17 + 37;
}
}
没有重写hasCode的类:
package hashset.and.hashcode;
public class ClassWithoutHashCode {
public int i;
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof ClassWithoutHashCode) {
ClassWithoutHashCode code = (ClassWithoutHashCode) o;
return code.i == i;
}
return false;
}
}
测试类:
package hashset.and.hashcode;
import java.util.HashSet;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
ClassWithHashCode c1 = new ClassWithHashCode();
ClassWithHashCode c2 = new ClassWithHashCode();
c1.i = 0;
c2.i = 0;
HashSet<ClassWithHashCode> set = new HashSet<ClassWithHashCode>();
set.add(c1);
System.out.println(set.contains(c2));
ClassWithoutHashCode co1 = new ClassWithoutHashCode();
ClassWithoutHashCode co2 = new ClassWithoutHashCode();
co1.i = 0;
co2.i = 0;
HashSet<ClassWithoutHashCode> set1 = new HashSet<ClassWithoutHashCode>();
set1.add(co1);
System.out.println(set.contains(co2));
}
}
执行的结果为:
true
false