Один и тот же объект используется в качестве ключа для двух записей в карте - PullRequest
0 голосов
/ 06 мая 2018

У меня есть класс Employee, как показано ниже.

class Employee {
int empId;
String empName;

public Employee() {
}

Employee(int empId, String empName) {
    this.empId = empId;
    this.empName = 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 int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + empId;
    result = prime * result + ((empName == null) ? 0 : empName.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Employee other = (Employee) obj;
    if (empId != other.empId)
        return false;
    if (empName == null) {
        if (other.empName != null)
            return false;
    } else if (!empName.equals(other.empName))
        return false;
    return true;
}}

Я использую этот объект класса Employee в качестве ключа в моей HashMap, как показано ниже.

    Map<Employee, String> empMap = new HashMap<>();
    Employee e1 = new Employee(123, "xyz");
    empMap.put(e1, "asd");
    System.out.println(empMap.size());
    System.out.println(empMap.get(e1));
    e1.setEmpId(122);
    empMap.put(e1, "asd");
    System.out.println(empMap.size());
    System.out.println(empMap.get(new Employee(122, "xyz")));
    System.out.println(empMap.get(new Employee(123, "xyz")));

    Set<Employee> mapEmpKeys = empMap.keySet();
    mapEmpKeys.forEach(emp -> {
        System.out.println("Employee ID: " + emp.getEmpId() + " Employee Name: " + emp.getEmpName());
    });

Вывод программы: 1 asd 2 asd null Employee ID: 122 Employee Name: xyz Employee ID: 122 Employee Name: xyz

У меня вопрос, даже если объекты в качестве ключей совпадают, я получаю размер карты равным 2. Может ли кто-нибудь объяснить мне, что после изменения объекта e1 Сотрудника путем установки его идентификатора на другое значение и добавления его снова в карту, дает размер 2 и когда я перебираю набор ключей карты, я получаю один и тот же объект для обеих записей. Ключи должны быть уникальными на карте, верно? Тогда почему я получаю один и тот же ключ объекта дважды? Спасибо!

1 Ответ

0 голосов
/ 06 мая 2018

Когда вы изменяете экземпляр, используемый в качестве ключа в HashMap, если вы изменяете свойства, используемые для определения равенства или для вычисления hashCode(), вы нарушаете HashMap.

Когда вы впервые поместили ключ на карту, он был помещен в корзину, которая соответствует hashCode(), вычисленному на основе значений 123 и "xyz".

Во второй раз, когда вы кладете тот же ключ на карту, он был помещен в другой контейнер, который соответствует hashCode(), вычисленному на основе значений 122 и "xyz".

Поскольку HashMap сначала находит контейнер, соответствующий ключу hashCode(), и только позже проверяет все ключи в этом баке на равенство ключей, если hashCode() данного ключа изменился, второй вызов put попытается найти его в новом ведре (соответствует новому hashCode()) и не найдет его там. Поэтому один и тот же ключ добавляется дважды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...