2014-04-25 40 views
3

這裏是我的測試類..Java的:爲什麼在HashMap中尋找相同的變量時不叫等於方法

import java.util.HashMap; 

public class Test { 

    public static void main(String[] args) { 
     A a = new A(0, 1); 
     HashMap<A, Integer> map = new HashMap<A, Integer>(); 
     map.put(a, (a.x + a.y)); 
     System.out.println(map.containsKey(a)); 
     System.out.println("----------------- "); 
     System.out.println(map.containsKey(new A(0, 1))); 
    } 

} 

,這裏是我的A級與哈希代碼和Eclipse生成等方法。

class A { 
    int x, y; 

    public A(int x, int y) { 
     super(); 
     this.x = x; 
     this.y = y; 
    } 

    @Override 
    public int hashCode() { 
     System.out.println(" in hashcode"); 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + x; 
     result = prime * result + y; 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     System.out.println(" in equal"); 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     A other = (A) obj; 
     if (x != other.x) 
      return false; 
     if (y != other.y) 
      return false; 
     return true; 
    } 

} 

程序的輸出是

in hashcode 
in hashcode 
true 
----------------- 
in hashcode 
in equal 
true 

我的問題是:(我知道哈希碼和平等的合同,爲什麼它被使用)

  1. 爲什麼在第一種情況下hashCode方法被稱爲twise?
  2. 爲什麼在第一種情況下平等不叫? JVM如何知道它是我們正在搜索的同一個變量?

回答

9

1)getHashCode在調用put時調用,當您調用時再調用contains。 2)在第一種情況下,散列表包含對a的引用,即內存中的地址,所以不需要調用equals。在第二種情況下,表查找找到一個,但這是與作爲參數給出的新A不同的對象,因此需要調用equals()以查明它們是否相等(它們可能不同並具有相同的散列碼,這將是一次碰撞)。

4

如果你看一看HashMap.containsKey的源代碼,你會發現下面的(從這裏取:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java#HashMap.containsKey%28java.lang.Object%29

public boolean containsKey(Object key) { 
    return getEntry(key) != null; 
} 


final Entry<K,V> getEntry(Object key) { 
    int hash = (key == null) ? 0 : hash(key.hashCode()); 
    for (Entry<K,V> e = table[indexFor(hash, table.length)]; 
    e != null; 
    e = e.next) { 
     Object k; 
     if (e.hash == hash && 
     ((k = e.key) == key || (key != null && key.equals(k)))) 
     return e; 
    } 
    return null; 
} 

最重要的部分是這個(k = e.key) == key || (key != null && key.equals(k))。 metod首先通過引用比較關鍵對象,然後使用equals方法進行比較,但前提是引用不同。

在您第一次致電containsKey時,關鍵引用將是相同的(同一對象)。在第二次調用中,引用將是不同的(「等於」對象的不同實例),因此調用equals

2

正如你可以@克雷西米爾-nesek粘貼代碼視圖,

首先得到的hashCode:int hash = (key == null) ? 0 : hash(key.hashCode());和 「散列碼」 打印

再對比一下Java對象標識符,(k = e.key) == key

1)在第一種情況下是相同的並且返回true。打電話來map.put你得到的第二「的哈希碼」

2),但在第二種情況下,對象標識符是不同的,所以調用的equals(... ... (key != null && key.equals(k))

「in equal」

相關問題