重寫equals方法的時候爲什麼需要重寫hashCode

@AllArgsConstructor
public class Pairs {
    @Getter
    @Setter
    private String key;
    @Getter
    @Setter
    private String value;
}

 

public static void main(String[] args) {
    Pairs pairs1 = new Pairs("name", "zhangsan");
    Pairs pairs2 = new Pairs("name", "zhangsan");

    System.out.println(pairs1.hashCode());
    System.out.println(pairs2.hashCode());
    System.out.println(pairs1.equals(pairs2));
    
    Map<Pairs, String> pairsMap = Maps.newHashMap();
    pairsMap.put(pairs1, pairs1.getValue());
    pairsMap.put(pairs2, pairs2.getValue());
    System.out.println(pairsMap.size());
}

 

程序運行結果

1221555852
1509514333
false
2

 

只重寫equals 不重寫hashCode

@AllArgsConstructor
public class Pairs {
    @Getter
    @Setter
    private String key;
    @Getter
    @Setter
    private String value;

    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (obj instanceof Pairs) {
            Pairs pairs = (Pairs) obj;

            // 比較各個屬性
            if (pairs.key.equals(key)
                    && pairs.value.equals(value)) {
                return true;
            }

            return false;
        }

        return false;
    }

}

 

程序運行結果

1221555852
1509514333
true
2

Map中存了兩個數值一樣的key,這個問題很嚴重。所以在重寫equals方法的時候,一定要重寫hashCode方法。

類似HashMap、HashTable、HashSet這種的都要考慮到散列的數據類型的運用。

 

既重寫equals又重寫hashCode

@AllArgsConstructor
public class Pairs {
    @Getter
    @Setter
    private String key;
    @Getter
    @Setter
    private String value;

    @Override
    public boolean equals(final Object obj) {
        if (obj == this) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (obj instanceof Pairs) {
            Pairs pairs = (Pairs) obj;

            // 比較各個屬性
            if (pairs.key.equals(key) && pairs.value.equals(value)) {
                return true;
            }

            return false;
        }

        return false;
    }

    @Override
    public int hashCode() {
        int result = 1;
        result = 24 * result +
                ((this.key == null) ?
                        1 : this.key.hashCode());
        result = 24 * result +
                ((this.value == null) ?
                        1 : this.value.hashCode());
        return result;
    }
}

 

程序運行結果

-1351635012
-1351635012
true
1

重寫了equals方法, 必須要重寫hashCode

對於兩個對象

  • hashCode() 值相同, equals() 不一定相同
  • equals() 相同, hashCode() 值一定相同

HashMap 存儲數據的時候,是取的 key 值的哈希值, 然後計算數組下標, 採用鏈地址法解決衝突, 然後進行存儲。 取數據的時候, 依然是先要獲取到哈希值, 找到數組下標, 然後 for 遍歷鏈表集合, 進行比較是否有對應的key。 比較關心的有兩點:

  • 無論是 put 還是 get 的時候, 都需要得到 key 的哈希值, 去定位 key 的數組下標;
  • 在 get 的時候, 需要調用 equals 方法比較是否有相等的key存儲過。

 

Reference

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章