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

时间:2019-10-09 07:29:28

标签: java hashmap

我有一个具有两个属性的类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对象中更改名称时,它的哈希值已更改,并且没有存储在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));

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

我可以想到的另一种理论解决方案是重新散列地图并将修改后的雇员对象保留在地图的正确存储区中,但是我看不到哈希图中的任何方法来对其进行散列。请提出建议,如果我在朝正确的方向思考,或者是否有其他解决方案。

P.S。所有这些目的都是为了了解哈希图,因此对如何解决此问题没有任何限制。

1 个答案:

答案 0 :(得分:1)

我认为empId可以唯一地标识员工。

所以equalshashCode方法只需要处理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());
    }