Java HashMap添加具有等于true和相同hashcode的对象

Java HashMap添加具有等于true和相同hashcode的对象,java,hashmap,equals,hashcode,Java,Hashmap,Equals,Hashcode,我正在尝试为HashMap创建自定义对象,并为hashcode和equals方法编写了代码。在HashMap中添加对象时,equals方法为true,hashcode为两个对象返回相同的值,而HashMap将两个对象作为不同的对象添加。这怎么可能呢? 下面是我的代码: class B { String name; int id; public B(String name, int id) { this.name=name; thi

我正在尝试为
HashMap
创建自定义对象,并为
hashcode
equals
方法编写了代码。在
HashMap
中添加对象时,
equals
方法为true,
hashcode
为两个对象返回相同的值,而
HashMap
将两个对象作为不同的对象添加。这怎么可能呢? 下面是我的代码:

class B {
    String name;
    int id;

    public B(String name, int id)
    {
        this.name=name;
        this.id=id;
    }

    public boolean equals(B b){
        if(this==b)
            return true;
        if(b==null)
            return false;
        if(this.name.equals(b.name) && this.id==b.id)
            return true;
        else
            return false;
    }

    public int hashcode(){
        return this.id;
    }

    public String toString(){
        return "name: "+name+" id: "+id;
    }
}
为了测试上述代码,我在主类中添加了以下内容:

HashMap<B,String> sample=new HashMap<>();
B b1 = new B("Volga",1);
B b2 = new B("Volga",1);
System.out.println(b1.equals(b2));
System.out.println(b1.hashcode()+"    "+b2.hashcode());
sample.put(b1, "wrog");
sample.put(b2,"wrog");
System.out.println(sample);

有人能解释一下为什么会这样吗?

这里有两个问题:

  • 您应该实现
    等于(对象)
    ()
  • 它需要是
    hashCode()
    ,而不是
    hashCode()
    ()
  • 工作实现可能如下所示:

    class B {
        String name;
        int id;
    
        public B(String name, int id) {
            this.name = name;
            this.id = id;
        }
    
        @Override
        public int hashCode() {
            return this.id;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            B other = (B) obj;
            if (id != other.id) {
                return false;
            }
            if (name == null) {
                if (other.name != null) {
                    return false;
                }
            } else if (!name.equals(other.name)) {
                return false;
            }
            return true;
        }
    
        @Override
        public String toString() {
            return "name: " + name + " id: " + id;
        }
    }
    

    作为一般建议,请确保指定
    @Override
    注释。您的IDE和Java编译器(
    javac
    )可以帮助您发现此类问题。

    实际上,由于输入错误(
    hashCode
    ),您既没有覆盖
    hashCode
    ,也没有覆盖
    Java.lang.Object
    equals
    方法以及在
    equals
    方法中使用错误的参数

    对两者都有效的实际实施将是:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        B b = (B) o;
        return id == b.id &&
                Objects.equals(name, b.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(name, id);
    }
    

    这个实现实际上是由IntelliJ IDEA生成的。我实际上喜欢这个实现,因为它使用了
    java.util.Objects.hash()
    方法,这大大简化了
    hashCode
    的生成,并在Java7中引入

    您必须重写
    equals(Object)
    &
    hashCode()
    方法,而不是
    equals(B)
    &
    hashCode()

    尝试使用以下签名实现这些方法&应该可以:

    @Override
    public boolean equals(Object o){...}
    
    @Override
    public int hashCode() {...}
    

    您还可以使用IDE的自动生成功能来生成这些方法。这样,就不会出现错误。

    您的equals方法不会覆盖Object中的方法。它应该以Object作为参数,而不是B。始终将
    @Override
    注释添加到应该重写或实现方法的方法中。不仅如此,如果你犯了刚才犯的错误,编译器将拒绝编译。此外,
    hashcode
    中也有打字错误。应该是
    hashCode
    ,大写
    C
    …谢谢,我错过了,这就是问题所在。现在工作很好!!!“如果您在IDE中工作,如Eclipse、IntelliJ IDEA、Netbeans等,请确保指定@Override注释。”该检查与IDE功能无关
    @Override
    将产生编译错误。因此,只需javac就足以检测到这一点。
    @Override
    public boolean equals(Object o){...}
    
    @Override
    public int hashCode() {...}