Пользовательский объект как ключ карты - PullRequest
0 голосов
/ 24 апреля 2019

Как я прочитал, если пользовательские объекты должны быть ключом карты, хэш-код и метод equals должны переопределять, но в моем случае это работает без переопределения. Может кто-нибудь сказать, пожалуйста, что не так?

    Map<Student,Integer> map = new HashMap<>();
    Student s1=new Student(1,"A");
    Student s2=new Student(2,"B");
    Student s3=new Student(3,"C");

    map.put(s1,1);
    map.put(s2,2);
    map.put(s1,3);

    for(Student s:map.keySet()) {
        System.out.println(map.get(s) + "->" + s.id + " " +s.name);
    }

Правильный вывод:

3-> 1 A

2-> 2 B

Ответы [ 3 ]

4 голосов
/ 24 апреля 2019

Это одно из свойств из equals метода: это рефлексивно. Что означает, что

x.equals(x) == true 

Объект всегда равен самому себе. В этом случае вы используете стандартную реализацию метода equals.

map.put(s1,1); 
map.put(s1,3);

и потому что реализация по умолчанию рефлексивна

s1.equals(s1) == true 

значение 1 заменено на 3

Однако результат будет другим, если вы сделаете что-то подобное

map.put(new Student(1,"A"),3);

s1.equals(new Student(1,"A")); 

Вам нужно переопределить hashCode и equals, чтобы все работало правильно.

2 голосов
/ 24 апреля 2019

Встроенный hashCode() и equals() отлично работает.Они согласованы в соответствии с требованиями HashMap (то есть: если hashCode() s не идентичны, equals() всегда будет возвращать false).Это потому, что каждый экземпляр объекта будет только equal() для себя.

Однако зачастую это не то, что вы хотите.В частности, без переопределения этих методов два экземпляра Student с одинаковыми полями не будут считаться равными.Таким образом, это напечатает три строки вместо одной:

Map<Student,Integer> map = new HashMap<>();
Student s1=new Student(1,"A");
Student s2=new Student(1,"A");
Student s3=new Student(1,"A");

map.put(s1,1);
map.put(s2,2);
map.put(s3,3);

for(Student s:map.keySet()) {
    System.out.println(map.get(s) + "->" + s.id + " " +s.name);
}

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

2 голосов
/ 24 апреля 2019

Если нет переопределяющего hashCode или метода equals, Java сравнивает ссылки на объекты.Таким образом, ссылка s1 совпадает со ссылкой s1, поэтому вы можете заменить s1 связанное значение другим.

Если вы создаете новый объект Student с такими же значениями атрибутов, что и s1 и попытайтесь вставить его в свою карту, у вас будет две разные пары.

...