开发者社区> 问答> 正文

有没有一种方法可以在Java中手动重新映射地图?

我有Employee两个属性的类。

public class Employee {

private int empId;
private String empName;

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;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Employee)) return false;
    Employee employee = (Employee) o;
    return getEmpId() == employee.getEmpId() &&
            Objects.equals(getEmpName(), employee.getEmpName());
    //return Objects.equals(getEmpName(), employee.getEmpName());
}

@Override
public int hashCode() {
    //return Objects.hash(getEmpId());
    return Objects.hash(getEmpId(), getEmpName());
}

} 我正在使用此类作为Hashmap中的键。

现在,当emp在这种情况下修改Employee对象的名称时修改原始对象时,我无法访问我最初保存在地图中的条目。只有当我将名称回滚到原始值时,我才能再次访问该对象。

这表明我在Employee对象中更改名称时,其哈希值已更改,并且未存储在Hashmap的正确存储区下。

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

    // Set Employee with Name Shashi
    Employee emp = new Employee();
    emp.setEmpId(1);
    emp.setEmpName("Shashi");

    // Add to Map
    map.put(emp, emp.getEmpName());

    // Modify The Original Employee object's Name
    emp.setEmpName("Shashi Bhushan");

    // This object does not exist as key in map now
    Assert.assertFalse(map.containsKey(emp));

    // Create object with same name(used when creating)
    Employee similarEmployee = new Employee();
    similarEmployee.setEmpId(1);
    similarEmployee.setEmpName("Shashi");

    // Hashcode check will pass, equals will fail
    Assert.assertFalse(map.containsKey(similarEmployee));
    Assert.assertNull(map.get(similarEmployee));

    // Create object with same name(modified name)
    Employee anotherSimilarEmployee = new Employee();
    anotherSimilarEmployee.setEmpId(1);
    anotherSimilarEmployee.setEmpName("Shashi Bhushan");

    // Hashcode check will fail
    Assert.assertFalse(map.containsKey(anotherSimilarEmployee));
    Assert.assertNull(map.get(anotherSimilarEmployee));

    // Now, if I roll back the name, i could again fetch using the new created object as well.
    // Since now this new object will be equivalent to the old object.
    emp.setEmpName("Shashi");
    Assert.assertTrue(map.containsKey(similarEmployee));
    Assert.assertNotNull(map.get(similarEmployee));

能够获取map中对象的问题的一种解决方案是使Employee类不可变。

我能想到的另一种理论解决方案是重新散列地图并将修改后的Employee对象保留在地图的正确存储区中,但我看不到哈希图中的任何方法来对其进行散列。

展开
收起
小六码奴 2019-10-09 18:00:24 1832 0
1 条回答
写回答
取消 提交回答
  • 我认为只有empId可以识别employee。 所以equals和hashCode方法只需要处理empId字段: @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Employee)) return false; Employee employee = (Employee) o; return getEmpId() == employee.getEmpId()); }

    @Override
    public int hashCode() {
        return Objects.hash(getEmpId());
    }
    
    2019-10-09 18:02:20
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载