java - HashMap 和 Hashcode

标签 java hashmap hashcode

理想情况下,根据定义,HashMap 不允许重复键;但我无法理解以下逻辑。

我已经定义了一个 Employee 类并覆盖了 equalshashcode 方法。

public class Employee {

    private String empID;
    public int hashCode() {
        int result = 17;
        result = 37 * result + empID.hashCode();
        return result;
    }
    public boolean equals(Object object) {
        boolean result = false;
        if (object instanceof Employee) {
            Employee employee = (Employee) object;
            result = (this.empID.equalsIgnoreCase(employee.getEmpID()));
        }
        return result;
    }
}
Employee e1 = new Employee("1");
Employee e2 = new Employee("2");

Map<Employee, String> empMap = new HashMap<Employee, String>();
empMap.put(e1, "Emp1");
empMap.put(e2, "Emp2");
Set<Employee> keys = empMap.keySet();
for (Employee e: keys)
{
    e.setEmpID("1");
}
for (Employee e: keys)
{
    System.out.println(e.getEmpID());
    System.out.println(e.hashCode());
}
System.out.println(empMap.get(new Employee("1")) );

我总是得到值 Emp1。如何获取值Emp2

最佳答案

我相信你的键和值是倒过来的。您应该使用 String 作为键,将 Employee 类用作值:

Map<String,Employee> empMap = new HashMap<>();
empMap.put("Emp1", e1);
empMap.put("Emp2", e2);

那么您的 Employee 类根本不需要 hashCode 和 equals 方法。您的 Employee 类不适合用作映射键,主要是因为键不应该更改其内部变量。您在迭代时只看到一个 ID 的原因是:

for (Employee e: keys)
{
    e.setEmpID("1");
}

由于三个原因,它被破坏了。 (1) 当键在 map 中时,您不得修改键的变量,因为 map 不会知道它。要更改与某个值关联的键,您必须从映射中remove() 那个映射,然后用新键put() 将它放回原处。 (2) 如果您同时遍历 map (除非您通过 map 的迭代器进行操作),无论如何都不允许修改 map 。 (3) 您为所有员工提供了相同的 key ,因此 map 无法区分他们。

想想你的 Employee 类的目的。如果您真的想将它用作映射,请删除 ID 的 setter ,因为使用该方法总是错误的。理想的映射键是完全不可变的和最终的。在equals方法中使用equalsIgnoreCase也是错误的,因为那样equals方法和hashCode方法不一致。 (如果 a.equals(b) 为真,则需要 a.hashCode() == b.hashCode(),否则 map 将无法正常工作。 ) 当你完成修复你的 Employee 类以用作映射键时,它只是 String 的一个烦人且不必要的包装器,但是你没有地方放置任何其他员工信息,这就是为什么我建议简单地交换键和值,这将一次性解决您的所有问题。

关于java - HashMap 和 Hashcode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25071948/

相关文章:

java - BrowserMobProxy 不会捕获 har 文件中的任何条目

java - 如何在Java中使用运行时对象打开多个文件?

java - 如何在Java中的Web服务中接收 HashMap ?

c++ - Hashmap 打印函数不更新集

java - 从 Java 的 HashCode 中获取值

algorithm - 探测哈希表

java - 在 SPring Boot 2.1.1 中扩展 GlobalMethodSecurityConfiguration 时出现错误,指出已定义 "methodSecurityInterceptor"

java - 创建并打印 HashMap<String, Integer>

java - 如何为记录设置自定义 equals/hashCode?

java - Spring 组件之间共享信息