【问题标题】:Why override equals not work for adding same objects in Map?为什么覆盖等于不适用于在 Map 中添加相同的对象?
【发布时间】:2019-09-28 07:15:49
【问题描述】:

如果你看这个程序,在 Location 类中,我们覆盖了两个方法(equals 和 hashcode),分别返回 false 和 110。我们正在创建 Location 类的一个实例并两次放入 map。当我们从 equals 方法返回 false 时,为什么 map 用 key 覆盖最后一个值?

class Location {

        long latitude;
        long longitude;

        public Location(long latitude,int longitude) {
            this.latitude = latitude;
            this.longitude = longitude;
        }

        @Override
        public boolean equals(Object obj) {
            return false;
        }

        @Override
        public int hashCode() {
            return 110;
        }

        @Override
        public String toString() {
            return String.format("Latitude := %d , Longitude :=%d ", latitude,longitude);
        }

    }

    Map<Location, String> locations = new HashMap<>();

    Location l1 = new Location(2,3); 
    locations.put(l1, "Mumbai");
    locations.put(l1,"Pune");       

    System.out.println(locations+ " with size of :"+locations.size());

【问题讨论】:

  • 为什么 map 用 key 覆盖最后一个值?是什么意思??
  • 我猜 HashMap 在调用 equals 之前比较相等 (==) 作为优化。请注意,您的 equals 方法违反了 Object.equals 的合同,这需要自反性。
  • 快速浏览HashMap source(从第611行开始),将引导您到第634行和((k = p.key) == key,即true
  • HashMap 依赖于equalshashCode 的正确实现。否则无法保证行为。
  • @ElliottFrisch 请注意you can do this

标签: java


【解决方案1】:

我查看了HashMap 的实现。显然您的Location::equals 从未被调用过,因为== 用于测试键的相等性。
原因是 - 感谢 chrylis - 您添加了两次相同的位置。
更改您的代码:

Location l1 = new Location( 2, 3 );
locations.put( l1, "Mumbai" );

Location l2 = new Location( 2, 3 );
locations.put( l2, "Pune" );

【讨论】:

  • 嗯?密钥类型是Location,而不是Integer
  • 抱歉,HashMap 是哈希的键。哈希是Integer。所以两个整数是比较的,没有别的。
  • 关键是不是散列。哈希用于对键进行分组以提高效率。
  • 我说了很多废话。你是绝对正确的。对不起。
猜你喜欢
  • 2012-02-26
  • 2023-04-01
  • 1970-01-01
  • 2012-11-05
  • 1970-01-01
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多