Java 检索hashmap冲突中的实际值

Java 检索hashmap冲突中的实际值,java,data-structures,map,hashmap,Java,Data Structures,Map,Hashmap,两个不同的对象可以具有相同的哈希代码并且相等。如何通过引用获取实际对象 例如: 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.lengt

两个不同的对象可以具有相同的哈希代码并且相等。如何通过引用获取实际对象

例如:

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));
   }
}
类狗{
公共字符串名称;
公犬(第n串){
this.name=n;
}
公共布尔等于(对象o){
if((Dog的(o instanceof)和((Dog)o).name.length()==this.name.length()){
返回true;
}否则{
返回false;
}
}
公共int hashCode(){
返回name.length();
}
@凌驾
公共字符串toString(){
返回名称;
}
}
公共类映射测试{
公共静态void main(字符串ar[]{
Map m=新的HashMap();
狗d1=新狗(“三叶草”);
犬d2=新犬(“abcdef”);
m、 put(首被告,新狗(“aiko1”))
m、 put(d2,新狗(“爱子”));
系统输出println(m.get(d1));
系统输出println(m.get(d2));
}
}
输出:-
爱子
爱子


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

因为您的两个键(
d1
d2
)是相等的(根据您对
eqauls(Object)
的实现),所以映射中没有两个元素-只有一个。对
put
的第二次调用将覆盖上一个值。

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

  • 首先,您重写了
    hashCode()
    方法
  • HashMap
    将首先查看它
  • 您正在使用
    name
    字段的
    length
    作为哈希代码
  • “clover”和“abcdef”都将返回相同的哈希代码,即6
  • 现在它是一个冲突状态,因此
    HashMap
    将下降到
    equals
    方法,以进一步检查它,并再次被您覆盖
  • 但在这里,
    equals
    中,您也在做同样的事情。这里还比较了
    name
    字段的长度
  • 在这种情况下,两个键相同,因此它将覆盖最后一个值
您可以验证它,但在
main
方法的末尾调用
m.size()


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

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

我不明白你的问题。您已经有了
d1
。您正在使用它作为键。缺陷是您的
equals()
方法。你说狗(“三叶草”)和狗(“abcdef”)是一样的。那么你期待什么呢?钥匙d2和d1是同一个!因此,m.put(d2,…)取代了entry(d1,Dog(“aiko1”))。我试图理解如果两个对象具有相同的哈希代码,hashmap是如何工作的?根据Hashcode契约,如果Hashcode是相同的,那么通过equals方法对象应该是相同的。当哈希代码相同时,有没有一种方法可以在java中检索d1值?如果两条狗的名字长度相同,你真的打算断言它们相等吗?比如说,Fido等于Spot?对我来说,这似乎是一个奇怪的断言。“根据Hashcode契约,如果Hashcode是相同的,那么通过equals方法对象应该是相同的。”这是错误的!反之亦然:如果两个对象相等,则它们必须具有相同的哈希代码。哈希代码方法应该努力为不同的对象生成不同的哈希代码,但它们可以是相同的。
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));
    }
}