【问题标题】:Retrieve actual value in hashmap collision在哈希映射冲突中检索实际值
【发布时间】:2014-05-10 08:42:13
【问题描述】:

两个不同的对象可以有相同的hashCode并且相等。如何通过引用获取实际对象?

例如:-

class Dog {
    public String name;
    public Dog(String n){
       this.name = n;
    }

    public boolean equals(Object o){
        if((o instanceof Dog) && ((Dog)o).name.length() == this.name.length()){
            return true;
        }else{
            return false;
        }
    }
    public int hashCode(){
        return name.length();
    }

    @Override
    public String toString(){
    return name;
    }
}
public class MapTest {
    public static void main(String ar[]){
        Map<Object, Object> m = new HashMap<Object, Object>();
        Dog d1 = new Dog("clover");
        Dog d2 = new Dog("abcdef");
        m.put(d1, new Dog("aiko1"))
        m.put(d2, new Dog("aiko"));
        System.out.println(m.get(d1));
        System.out.println(m.get(d2));
   }
}

输出:-
爱子
爱子

然而,d1 的值是 aiko1,但是当我们获取时,打印的值是 aiko。我们如何获取实际的 d1 值?

【问题讨论】:

  • 我不明白你的问题。您已经拥有d1。您正在使用它作为密钥。
  • 缺陷在于您的equals() 方法。你说 Dog("clover")` 和 Dog("abcdef") 是一样的。那么你期待什么?键 d2 和 d1 相同!因此 m.put(d2,...) 替换条目 (d1, Dog("aiko1"))。
  • 我想了解如果两个对象具有相同的哈希码,哈希图是如何工作的?通过 Hashcode 合约,如果 hashcode 相同,则通过 equals 方法对象应该相同。当哈希码相同时,有没有一种方法可以在 java 中检索 d1 值?
  • 如果两只狗的名字长度相同,你真的打算断言它们相等吗?例如,Fido 等于 Spot 吗?这对我来说似乎是一个奇怪的断言。
  • "通过 Hashcode 合约,如果 hashcode 相同,那么通过 equals 方法的对象应该相同。" 这是错误的!反之亦然:如果两个对象相等,则它们必须具有相同的哈希码。哈希码方法应该努力为不相等的对象产生不同的哈希码,但它们可能是相同的。

标签: java data-structures map hashmap


【解决方案1】:

让我解释一下HashMap 在这种情况下是如何工作的。

  • 首先你已经覆盖了hashCode()方法
  • HashMap 会先看看。
  • 您正在使用 lengthname 字段作为哈希码。
  • “clover”和“abcdef”都将返回相同的哈希码,即6。
  • 现在它是一个碰撞状态,因此 HashMap 将下降到 equals 方法来进一步检查它,这又被你覆盖了。
  • 但在equals 中,您又在做同样的事情。您还在这里比较了name 字段的长度。
  • 在这种情况下,两个键是相同的,因此它将覆盖最后一个值。

您可以验证它,但在 main 方法的末尾调用 m.size()


但我建议使用String 作为名称字段的键。

Map<String, Object> m = new HashMap<String, Object>();

在这种情况下,您不需要覆盖 hashCodeequals

import java.util.HashMap;
import java.util.Map;

class Dog {
    public String name;

    public Dog(String n) {
        this.name = n;
    }

    @Override
    public String toString() {
        return name;
    }
}

public class MapTest {
    public static void main(String ar[]) {
        Map<String, Object> m = new HashMap<String, Object>();
        Dog d1 = new Dog("clover");
        Dog d2 = new Dog("abcdef");
        m.put(d1.name, new Dog("aiko1"));
        m.put(d2.name, new Dog("aiko"));
        System.out.println(m.get(d1.name));
        System.out.println(m.get(d2.name));
    }
}

【讨论】:

    【解决方案2】:

    由于您的两个键(d1d2)相等(根据您对 eqauls(Object) 的实现),因此地图中没有两个元素 - 只有一个。第二次调用put覆盖之前的值。

    【讨论】:

      猜你喜欢
      • 2015-08-17
      • 2017-10-04
      • 2020-04-01
      • 2011-06-24
      • 2021-04-13
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 2018-07-17
      相关资源
      最近更新 更多