學習:重寫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

 

符合預期。證畢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM