我已经读过,如果自定义对象需要作为map的键,则需要覆盖hashcode和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
答案 0 :(得分:4)
它是equals
方法中的properties之一:它是自反的。这意味着
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
才能使其正常工作。
答案 1 :(得分:2)
如果没有覆盖的hashCode或equals方法,则Java将比较对象引用。因此,s1
引用与s1
引用相同,因此您可以将s1
关联值替换为另一个值。
如果您创建的新Student
对象的属性值与s1
相同,并尝试将其插入到地图中,则会有两个不同的对。
答案 2 :(得分:2)
内置hashCode()
和equals()
可以正常工作。它们与HashMap
要求的方式一致(即:如果hashCode()
不相同,则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);
}
(注意:从技术上讲,这完全是正确的,但不一定是大多数阅读您的代码的人都会期望的。)