重写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

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