【问题标题】:hashCode and Equals doesn't work properly in Map keyshashCode 和 Equals 在 Map 键中无法正常工作
【发布时间】:2014-09-11 05:51:53
【问题描述】:

我有 Employee 类,并希望将此类用作 HashMap 中的键,该映射的值将是一个字符串。然而,为了实现这一点,我重写了 Employee 类本身中的 equals 和 hashcode 方法。我有另一个类来测试 Employee 类键是否可以正常工作。经过测试,我发现 map 存储了重复的键。请在下面找到源代码和输出:

Employee.java

public class Employee {

    private int empId;
    private String empName;
    private int empAge;

    Employee(){}

    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public int getEmpAge() {
        return empAge;
    }

    public void setEmpAge(int empAge) {
        this.empAge = empAge;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj == null) return false;
        if(!(obj instanceof Employee)) return false;

        Employee e = (Employee)obj;

        return e.empId == this.empId;
    }

    @Override
    public int hashCode() {
        return this.empId;
    }

    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return "Id : "+empId+" Name : "+empName+" Age : "+empAge;
    }
}

TestEmployee.java

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


public class TestEmployee {

    /**
     * @param args
     */
    public static void main(String[] args) {

        Map<Employee, String> empMap = new HashMap<Employee, String>();

        Employee emp1 = new Employee();
        emp1.setEmpId(10);
        emp1.setEmpName("A");
        emp1.setEmpAge(20);

        Employee emp2 = new Employee();
        emp2.setEmpId(20);
        emp2.setEmpName("B");
        emp2.setEmpAge(21);

        empMap.put(emp1, "1");
        empMap.put(emp2, "2");

        System.out.println(empMap);

        emp1.setEmpId(20);

        System.out.println(" emp1.equals(emp2) : "+emp1.equals(emp2));
        System.out.println(" emp1.hashCode() : "+emp1.hashCode()+" emp2.hashCode() : "+emp2.hashCode());

        System.out.println(empMap);

    }

}

输出:

{Id : 20 Name : B Age : 21=2, Id : 10 Name : A Age : 20=1}
 emp1.equals(emp2) : true
 emp1.hashCode() : 20 emp2.hashCode() : 20
{Id : 20 Name : B Age : 21=2, Id : 20 Name : A Age : 20=1}

请告诉我如何在映射键中使用唯一员工 - 唯一性将根据员工 ID 决定。

【问题讨论】:

  • HashCode 仅在您插入地图时计算。每次您使用另一个引用更改插入到地图中的对象值时,都不会计算它。

标签: java overriding equals hashcode


【解决方案1】:

当对象在哈希图中时,不要更新用于哈希码的值。哈希码将用于决定放置对象的位置。如果您之后对其进行更新,则此更新不会被哈希映射“拾取”,因此充其量您有重复项,最坏的情况是您无法再检索与更新后的键相关的值。

更新

请查看 javadoc 以获取更多信息,但高级别的 HashMap 会根据键的哈希码选择一个存储桶来放入值。如果您尝试使用键检索值,它将查看键的哈希码,确定它应该在哪个存储桶中,然后检查该存储桶并检索值。

但是,如果在 put() 和 get() 之间 key 的 hashcode 发生变化,hashmap 可能会将其放入桶“A”并尝试将其放入桶“B”。

【讨论】:

  • 你能解释一下在这种情况下如何从 hashmap 中获取数据吗?还有一件事,我试图交换员工 ID,当我尝试获取数据时,我得到了空值。 emp1.setEmpId(20); emp2.​​setEmpId(10);
  • 那个桶存储在哪里,在堆空间中?
【解决方案2】:

在您的 equals 方法中,而不是使用 '==' 参考比较使用 equals 方法 因为 '==' 比较检查引用相等而不是值比较。 喜欢 返回 e.empId.equals(this.empId);

Java Integer 类正确地覆盖 equals,它会给你正确的结果。

【讨论】:

  • 比较不是问题,因为 Ravi 是在比较整数。
  • 我有点想否决这个答案。 OP 在问别的问题。
猜你喜欢
  • 1970-01-01
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 2022-07-07
  • 1970-01-01
  • 2015-01-28
  • 2013-07-28
  • 2021-03-17
相关资源
最近更新 更多