理想情况下,根据定义,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)密钥在地图中时,请勿修改它的变量,因为地图不会知道它。要更改与值关联的键,必须从地图
remove()
映射,然后put()
用新键将其重新插入。 (2)如果您同时在地图上进行迭代,则无论如何都不允许修改地图(除非您通过地图的迭代器进行操作)。 (3)您要为所有员工提供相同的密钥,因此地图无法区分他们。考虑一下Employee类的目的。如果您确实想将其用作映射键,请删除ID的setter,因为使用该方法始终是错误的。理想的映射键是完全不变的且是最终的。在equals方法中使用equalsIgnoreCase也是错误的,因为那时equals方法与hashCode方法不一致。 (如果
a.equals(b)
为true,则要求a.hashCode() == b.hashCode()
,否则该映射将无法正常工作。)到您完成固定Employee类以用作映射键的时间时,它只是一个烦人且不必要的包装器在String周围,但是您没有地方放置其他任何员工信息,这就是为什么我建议简单地交换键和值,这将一劳永逸地解决所有问题的原因。