理想情况下,根据定义,HashMap
不允许重复键;但我无法理解以下逻辑。
我已经定义了一个 Employee
类并覆盖了 equals
和 hashcode
方法。
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/