2017-06-15 23 views
-3

我已經寫具有Student類和學生目的如下被用作鍵 一個代碼,什麼是hashmap碰撞?並在我的代碼中發生?

public class ExampleMain01 { 

    private static class Student{ 
     private int studentId; 
     private String studentName; 

     Student(int studentId,String studentName){ 
      this.studentId = studentId; 
      this.studentName = studentName; 
     } 

     @Override 
     public int hashCode(){ 
      return this.studentId * 31; 
     } 

     @Override 
     public boolean equals(Object obj){ 
      boolean flag = false; 
      Student st = (Student) obj; 


      if(st.hashCode() == this.hashCode()){ 
       flag = true; 
      } 

      return flag; 
     } 

     @Override 
     public String toString(){ 
      StringBuffer strb = new StringBuffer(); 

      strb.append("HASHCODE ").append(this.hashCode()) 
      .append(", ID ").append(this.studentId) 
      .append(", NAME ").append(this.studentName); 

      return strb.toString(); 
     } 

     public int getStudentId() { 
      return studentId; 
     } 

     public String getStudentName() { 
      return studentName; 
     } 
    } // end of class Student 

    private static void example02() throws Exception{ 
     Set<Student> studentSet = new HashSet<Student>(); 
     studentSet.add(new Student(12, "Arnold")); 
     studentSet.add(new Student(12, "Sam")); 
     studentSet.add(new Student(12, "Jupiter")); 
     studentSet.add(new Student(12, "Kaizam")); 
     studentSet.add(new Student(12, "Leny")); 

     for(Student s : studentSet){ 
      System.out.println(s); 
     } 
    } // end of method example02 

    private static void example03() throws Exception{ 
     Map<Student, Integer> map = new HashMap<Student,Integer>(); 

     Student[] students = new Student [] { 
      new Student(12, "Arnold"), 
      new Student(12, "Jimmy"), 
      new Student(12, "Dan"), 
      new Student(12, "Kim"), 
      new Student(12, "Ubzil") 
     }; 


     map.put(students[0], new Integer(23)); 
     map.put(students[1], new Integer(123)); 
     map.put(students[2], new Integer(13)); 
     map.put(students[3], new Integer(25)); 
     map.put(students[4], new Integer(2)); 

     Set<Map.Entry<Student, Integer>> entrySet = map.entrySet(); 

     for(Iterator<Map.Entry<Student, Integer>> itr = entrySet.iterator(); itr.hasNext();){ 
     Map.Entry<Student, Integer> entry = itr.next(); 
     StringBuffer strb = new StringBuffer(); 

     strb.append("Key : [ ").append(entry.getKey()).append(" ], Value : [ ").append(entry.getValue()).append(" ] "); 

      System.out.println(strb.toString()); 
     } 

    } // end of method example03  

    public static void main(String[] args) { 
     try{ 

      example02(); 
      example03(); 



     }catch(Exception e){ 
      e.printStackTrace(); 
     } 

    }// end of main method 

} // end of class ExampleMain01 

在Student類上面的代碼的哈希碼和equals是這樣實現的,

@Override 
    public int hashCode(){ 
     return this.studentId * 31; 
    } 

    @Override 
    public boolean equals(Object obj){ 
     boolean flag = false; 
     Student st = (Student) obj;   

     if(st.hashCode() == this.hashCode()){ 
      flag = true; 
     } 

     return flag; 
    } 

現在,當我編譯和運行該代碼,

在方法example02的代碼給出的輸出作爲

HASHCODE 372, ID 12, NAME Arnold 

即設置只保存一個對象,

我明白,作爲所有對象的鍵具有相同的hashCode因此只有單一的目的在於,水桶372我說得對不對?

同樣方法example03()得到輸出作爲

Key : [ HASHCODE 372, ID 12, NAME Arnold ], Value : [ 2 ] 

從我們可以看到,作爲密鑰返回相同的散列碼, HashMap中僅保持單一密鑰值對上述方法。

所以我的問題是沒有衝突發生在哪裏?

可以一鍵可以指向多個值嗎?

哪裏LinkedList的概念來而尋找各個鍵的值?

可有人請給我解釋一下上面的東西對於我有共同的例子嗎?

+2

哈希衝突不是一個問題,你的問題是,你提供平等的ID,你只檢查在'equals'事實方法。 – Tom

回答

1

什麼是散列表映射?

沒有「hashmap collision」這樣的事情。

有這樣的事,作爲「散列碼衝突」。當兩個對象具有相同的哈希碼但不相等時會發生這種情況。

Hashcode方法的碰撞是沒有問題的......除非它經常發生。一個設計合理的散列表數據結構(包括HashMapHashSet)將應付碰撞,但如果碰撞概率太高,性能將受到影響。


確實[哈希碼碰撞]發生在我​​的代碼?

No.

與您的代碼的問題是不是由於哈希碼碰撞:

  • equals方法實際上是說兩個Student對象相等當且僅-如果它們具有相同的哈希碼。由於您的散列碼僅根據ID計算,這意味着任何具有相同ID的對象都等於,定義爲

  • 然後,您添加大量具有相同ID(12)和不同名稱的Student對象。顯然,這意味着它們是平等的。這意味着HashSet只會在任何特定時間持有其中一個。


所以我的問題是沒有衝突發生在哪裏?

的問題是,Student對象都是等於

一個鍵可以指向多個值嗎?

這是一個HashSet不是HashMap。沒有「鑰匙」。 A Set是一組獨特的價值觀...其中唯一意味着成員不平等。

在查找各個密鑰的值時,鏈表概念來自哪裏?

如果您正在討論LinkedList課程,它不會涉及它。

如果你一般在談論鏈表,實現HashSet可以用的鏈表來表示哈希鏈。但是這是一個實現細節,而不是對你的例子有什麼影響。

(如果你真的想知道HashSet作品如何使用谷歌搜索「java.util.HashSet中源」和閱讀的源代碼。請注意,實現在不同的Java版本的不同。)


一個鍵可以指向多個值嗎?

號的Map API不支持。

不過,當然,你可以使用這樣的地圖:

Map<Key, List<Value>> myMultimap = ..... 
+0

感謝您的回覆。這非常有幫助。我的第二個問題是,在hashmap中,密鑰是否可以映射到多個值?而關於鏈表的問題是,在獲取散列表中每個鍵的值時,使用鏈表數據結構。這是真的嗎?如果是的話,它是如何工作的,你能解釋我嗎? –

+0

*「我的關於鏈表的問題是,在獲取hashmap中每個鍵的值時,會使用一個鏈表數據結構。是真的嗎?如果是,它是如何工作的,你能解釋我嗎?」 - 我回答了這兩個問題。我的答案是**閱讀源代碼** ...因爲在StackOverflow答案中正確解釋太複雜。 –

+0

@RahulShivsharan相關:https://stackoverflow.com/questions/44031592/will-similar-strings-in-hashmap-lead-to-increased-chance-of-collisions/44046106#44046106和https://stackoverflow.com /問題/ 43911369/HashMap中的Java-8實現/ 43924719#43924719 – Eugene

相關問題