2014-08-30 98 views
-2

我想檢索HashMap中的另一個元素的值,覆蓋equals和hashcode方法。當我爲student1和student3使用相同的哈希碼並且這兩個對象相等時,爲什麼rollId返回null?理想的情況下,它應該返回我3.下面的代碼片段:Map HashCode和Equals

主類

public static void main(String[] args) { 
    Map<Student, Integer> studentMap = new HashMap<Student, Integer>(); 
    Student student1 = new Student(); 
    student1.setRollId(1); 
    Student student2 = new Student(); 
    student2.setRollId(2); 
    studentMap.put(student1, 1); 
    studentMap.put(student2, 2); 
    for (Entry<Student, Integer> entry : studentMap.entrySet()) { 
     if (entry.getValue().equals(1)) { 
      student1.setRollId(3); 
     } 
    } 
    Student student3 = new Student(); 
    student3.setRollId(3); 
    System.out.println("Student1 HashCode " + student1.hashCode() 
      + " Student3 HashCode " + student3.hashCode()); 
    System.out.println("Object Equal === > " + student1.equals(student3)); 
    Integer rollId = studentMap.get(student3); 
    System.out.println("RollId is " + rollId); 

} 


學生班級

private Integer rollId; 

public Integer getRollId() { 
    return rollId; 
} 

public void setRollId(Integer rollId) { 
    this.rollId = rollId; 
} 

@Override 
public int hashCode() { 
    return rollId; 
} 

@Override 
public boolean equals(Object obj) { 
    Student student = (Student)obj; 
    if(this.rollId.equals(student.getRollId())) 
    { 
     return true; 
    } 
    return false; 

} 
+0

你應該張貼整個代碼,而不是片段讓助手可以測試你的代碼。 – 2014-08-30 18:18:34

回答

1

HashMap最終將鍵值對存儲在表中,並且它使用給定鍵的哈希碼來計算表中其索引值。

當修改rollId屬性,則也將修改密鑰,這反過來會導致在內部表中的查找爲一個不同的指數大於所述一個地圖的哈希碼原本用於存儲值。

例如,表格最初可能已經被分配了一定的容量爲16,並且兩個對條目被存儲在索引1和2(給定Student對象中設置的rollId)。將散列鍵從1更改爲3後,映射將搜索 索引3,該索引不存儲任何值。

1

不能更改後的哈希鍵它放在地圖上,並期望地圖繼續正常工作。當您想要更改密鑰時,您必須刪除該項目,更改密鑰並重新插入。

從Java文檔:

注意:如果使用可變對象作爲map的key很大,一定要小心。如果對象的值以影響等於比較的方式更改,而對象是地圖中的關鍵字,則不會指定地圖的行爲。

+0

謝謝@Gene。明白了...這是一個可變的物體。 Upvote的答案。 – 2014-08-30 18:25:16

+0

這個答案雖然是一個真實的陳述,但並沒有在他的代碼中解釋問題.. studentMap沒有添加任何條目..所以student1 rollId從不改變。查看下面的回答 – ErstwhileIII 2014-08-30 19:02:23

+1

@ErstwhileIII也許他在看完它後改變了他的代碼?但是這個'studentMap.put(student1,1); studentMap.put(student2,2);'當我寫我的答案時在那裏。 – Gene 2014-08-30 21:02:12

0

您的代碼存在的問題是您沒有爲studentMap添加任何值。此外,我不明白你爲什麼使用整數RollId並從你的hashCode計算int。如果你確實需要Integer來獲得更大的範圍,那麼32位的hashcode(如你所計算的)有可能產生不同的rollIds的副本。考慮更改爲int/

試試這個代碼:

StudentDriver類

package com.example.student; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.Map.Entry; 

public class StudentDriver { 
    private static Student student1, student2, student3; 

    public static void main(String[] args) { 
     Map<Student, Integer> studentMap = new HashMap<Student, Integer>(); 

     student1 = new Student(); 
     student2 = new Student(); 

     student1.setRollId(1); 
     student2.setRollId(2); 

     studentMap.put(student1, student1.getRollId()); 
     studentMap.put(student2, student2.getRollId()); 

     for (Entry<Student, Integer> entry : studentMap.entrySet()) { 
      System.out.println("Entry information: " + entry.getValue()); 
      if (entry.getValue().equals(1)) { 

       student1.setRollId(3); 
      } 
     } 

     student3 = new Student(); 
     student3.setRollId(3); 

     System.out.println("Student1 Hashcode = " + student1.hashCode() 
          +", Student3 Hashcode = " + student3.hashCode()) ; 
     System.out.println("Object equal ==> " + student1.equals(student3)); 
     Integer rollId = student3.getRollId(); 
     System.out.println("RollId is " + rollId); 
    } 
} 

Student類

package com.example.student; 

public class Student { 
    // Object fields 
    private Integer rollId; 

    public Integer getRollId() { 
     return rollId; 
    } 
    public Student setRollId(Integer rollId) { 
     this.rollId = rollId; 
     return this; 
    } 

    @Override 
    public int hashCode() { 
     return rollId.intValue(); 
    } 

    @Override 
    public boolean equals(Object other) { 
     return other instanceof Student && ((Student)other).getRollId() == rollId; 
    } 
}