簡體   English   中英

自定義對象作為Map鍵

[英]Custom object as Map key

正如我已經讀到的,如果自定義對象需要成為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安

2-> 2 B

它是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")); 

您將需要覆蓋hashCodeequals使其正常工作。

如果沒有覆蓋的hashCode或equals方法,則Java將比較對象引用。 因此, s1引用與s1引用相同,因此可以將s1關聯值替換為另一個值。

如果創建一個具有與s1相同的屬性值的新Student對象,然后嘗試將其插入到地圖中,則將有兩個不同的對。

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

(注意:從技術上講,這完全是正確的,但不一定是大多數閱讀您的代碼的人都會期望的。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM