学习:重写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

 

符合预期。证毕。

上一篇:ORACLE查找并解除死锁进程


下一篇:前沿分享|阿里云数据库事业部资深技术专家、生态工具产品部负责人 陈长城:一站式在线数据管理平台DMS技术解读