我有一个循环填充HashMap
. 它根据原则工作 - 对于每个部门负责人(例如:会计),都有一个以该部门员工列表形式存在的值。即:首长是关键,下属的名单就是名单。当我执行循环时,我怎么会得到几个相同的键。我阅读了 Map 存储唯一键或覆盖它们以代替现有键的所有资源。如何解决这个问题(也许有删除所有重复键的选项)?这甚至是怎么发生的?
PS 在类本身中,equals 和 hashCode 被重新定义。同样在 Gate、Depatrment 和 Room 类中。
员工:
public class Employee extends EmployeeGeneral {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Employee)) return false;
Employee that = (Employee) o;
return room.equals(that.room) && department.equals(that.department) && upDepartment.equals(that.upDepartment) && gate.equals(that.gate);
}
@Override
public int hashCode() {
return Objects.hash(room, department, upDepartment, gate);
}
private static final long serialVersionUID = 372342343809L;
private Room room;
private Department department;
private Department upDepartment;
private Gate gate;
public static final Field ROOM;
方法:
for (MSEmployee m : employees) {
MSEmployee manager = msEmployeeRepository
.findFirstByDocID(departmentManagerMap.get(m.getDepartment().getId()));
if (manager == null) continue;
List<MSEmployee> msEmployeeList = msEmployeeRepository
.findAllByIdInAndDepartmentDocIdIn(employeesIds, manager.getDepartmentDocId());
employeesWithManagers.put(manager, msEmployeeList);
}
结果:
要覆盖 hashCode,建议使用 final 字段:hashmap 的工作原理大致如下:从对象中获取一个哈希码,这个哈希码通常确定对象在关联数组中的位置(在一个哈希映射)。例如:哈希映射我们有大小 16,对象的哈希码是 31,所以这个对象将适合位置 31%16=15(索引)。也就是说,要从映射中获取值,我们只需引用索引,就像在常规数组中一样,这就是为什么使用 hashset hashmap 如此之快。当发生冲突时(即不同对象的哈希码相同),在此映射中,这些对象被放置在相同的索引处,但在单链表中。而当我们想通过索引获取一个对象时,我们看到:这里我们有一个单链表,所以我们必须使用线性搜索找到我们需要的对象——这就是覆盖的 equals () 发挥作用的地方。如果您在 intellij 中工作,请按组合键 alt+insert(windows) ,菜单中会出现一个生成器,您需要在列表中选择 equals + hashcode,然后开发环境将为您完成所有工作。我建议在覆盖这些方法时使用,例如,员工 ID 是一个私有的最终字段,然后只需要它,前提是每个员工的 ID 都是唯一的
如果您有相同的 Employee 哈希码,那么根据显示的代码,逻辑上只有 2 个选项:
PS 为什么要在 hashCode() 和 equals() 中添加一个 public static final 字段?它不参与雇员状态。这是一个对所有员工实例都相同的常量。