我已经读过,如果自定义对象需要是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.
它是properties方法的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
才能使其正常工作。
如果没有重写的hashCode或equals方法,Java会比较对象引用。因此,s1
引用与s1
引用相同,因此您可以将s1
相关值替换为另一个。
如果您使用与Student
相同的属性值创建新的s1
对象,并尝试将其插入到地图中,则您将拥有两个不同的对。
内置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);
}
(注意:从技术上讲,这一切都是完全正确的,但不一定是大多数人阅读你的代码所期望的。)