自定义对象为Map键

问题描述 投票:0回答:3

我已经读过,如果自定义对象需要是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.

java collections hashmap equals hashcode
3个回答
4
投票

它是properties方法的equals之一:它是反身的。意思就是

x.equals(x) == true 

对象总是等于它自己。在这种情况下,您将继承equals方法的默认实现。

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

并且因为默认实现是反身的

s1.equals(s1) == true 

价值13取代

但是如果你做这样的事情会有不同的结果

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

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

您需要覆盖hashCodeequals才能使其正常工作。


2
投票

如果没有重写的hashCode或equals方法,Java会比较对象引用。因此,s1引用与s1引用相同,因此您可以将s1相关值替换为另一个。

如果您使用与Student相同的属性值创建新的s1对象,并尝试将其插入到地图中,则您将拥有两个不同的对。


2
投票

内置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);
}

(注意:从技术上讲,这一切都是完全正确的,但不一定是大多数人阅读你的代码所期望的。)

© www.soinside.com 2019 - 2024. All rights reserved.