HashMap添加具有等于true和相同哈希码的对象

时间:2018-08-17 07:04:09

标签: java hashmap equals hashcode

我正在尝试为HashMap创建自定义对象,并为hashcodeequals方法编写了代码。在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);

这将产生以下输出:

true
1    1
{name: Volga id: 1=wrog, name: Volga id: 1=wrog}

有人可以解释为什么会这样吗?

3 个答案:

答案 0 :(得分:6)

您在这里遇到了两个问题:

  1. 您应该实施equals(B)Javadoc)而不是实施equals(Object)
  2. 它必须是hashCode(),而不是hashcode()Javadoc

可能有效的实现 如下所示:

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)可以帮助您发现此类问题。

答案 1 :(得分:3)

实际上,由于打字错误(您使用的是hashCode)和错误的用法,您既不会覆盖equals的{​​{1}}也不是java.lang.Object的{​​{1}}方法hashcode方法中的参数。

对两者都有效的实际实现是:

equals

此实现实际上是由IntelliJ IDEA生成的。我真正喜欢这种实现的地方是,它使用@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); } 方法,大大简化了java.util.Objects.hash()的生成,并且是Java 7中引入的。

答案 2 :(得分:1)

您必须覆盖 public ProductPriceMap() { Id(x => x.id); Map(x => x.purchase_price); Map(x => x.p_cur_code); Map(x => x.p_rate); Map(x => x.sale_price); Map(x => x.s_cur_code); Map(x => x.s_rate); Map(x => x.quantity); Map(x => x.deleted); Map(x => x.create_date); Map(x => x.update_date); References(x => x.users, "id").ForeignKey("user_id").Cascade.None(); References(x => x.product, "id").ForeignKey("product_id").Cascade.None(); HasOne(x => x.product); // HasMany(x => x.product).ForeignKeyConstraintName("price_id").Cascade.None(); // References(x => x.currency, "code").ForeignKey("p_cur_code").Cascade.None(); // References(x => x.currency, "code").ForeignKey("s_cur_code").Cascade.None(); Table("productprice"); } equals(Object)方法,而不是hashCode()equals(B b)

尝试实现具有以下签名的方法,它应该可以工作:

hashcode()

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