JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Java 新手區  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to postflat modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 Re:HashMap關於hashCode()與equals()的問題 [Re:kentyeh]
weberhwang





發文: 45
積分: 0
於 2018-05-17 01:54 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
Hashtable跟HashMap太像(兩者差Hashtable有thread safe效果),我搞混了,我要問的應該是HashTable

至於下面這句話,是因為我看了官方Hashtable.java的程式碼,然後再加上自己的程式實驗所得出的結論

「當hashcode相等時,還要再用equals()去比較,若equals相等,則才會覆蓋。」
但無法理解,為何hashcode相同了,還要再用equals比較一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }
 
        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }
 
        addEntry(hash, key, value, index);
        return null;
    }


先說明我實驗的案例
由於<key,value>裡面key的部份,是可以放物件的,
所以我想在key跟value都故意放入「相同」的 員工 這個類別實體物件,
只要員工編號的hashcode相同(但我不要在key的地方直接放員工編號,我故意要放員工物件),就放不進去Hashtable → 這是我想要的結果

員工有兩個屬性 員編、姓名
改寫員工的equals()方法,要員編、姓名都相同,才算是相同
改寫員工的hashcode()方法,利用員編的hashcode做為回傳值 ← 為了在key欄位做hashcode比較時,會以員工編號的hashcode為比較基準,故改寫。

下面是程式碼TestHashTable.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.util.Hashtable;
import java.util.Map;
 
class Employee {
  private Integer empno;
  private String empname;  
 
  public Employee(){
   this.empno = 0;
   this.empname = "";  
  }
  
  public Employee(Integer empno,String empname){
    this.empno = empno;
    this.empname = empname;
  }
 
  // Override Object 類別的 equals(Object obj) 方法
  // 改寫equals大多會有下面2步驟
  // Step 1.先判斷兩個物件的「參考變數」是否指向同一個實體(指向同一個記憶體位置),
  //        若是,就一定為同物件了,直接判定相等。
  // Step 2.用(Object類別的)getClass()來確定是否隸屬於同一個class的物件
  //        若相同,則「加入自己的邏輯判斷是否為同一物件」
  //        例如:員工編號相同,就是同一個物件
  //              或  員工姓名相同,就視為同一個物件
  //              或  員工編號+員工姓名 皆相同,才視為同一個物件
 
  @Override
  public boolean equals(Object obj) {
 
  // Step 1 
  if (this == obj) return true;
      
  // Step 2                     
  if(obj != null && getClass() == obj.getClass()) {    
    if(obj instanceof Employee) {
      Employee e = (Employee)obj;
 
      //這邊是利用 員編號+員工姓名 皆相同,則視為同一個物件
      if (empno.equals(empno) && empname.equals(e.empname)) {  
        return true;
      }
    }
  }        
  return false;
}
 
  
  // Override Object 類別的 hashCode() 方法
  @Override
  public int hashCode() {
 
    //因為Hashtable的key,是以物件的hashCode()為key
    //上面的 equals()是採用兩個屬性:姓名、員編來判別,
    //所以若是hashCode的部份,只考慮員編,而沒考慮姓名來做hashcode的話,應該只員編相同就會放不進Hashtable才對,
    //比如下面我以員工編號的hashCode()做為hashCode()回傳值。
    //照說會發生同員編但不同員工姓名的物件,在填入至同一個Hashtable時,就會放不進去。但實際測,似乎不是這樣。
    return this.empno.hashCode();
  }
}
 
public class TestHashTable {
   
  public static void main(String[] args) {
     
    Employee e1 = new Employee(7001, "小明");
    Employee e2 = new Employee(7001, "小華");
 
    Map ht1 = new Hashtable();
 
    ht1.put(e1,e1);
    ht1.put(e2,e2); 
              
     
    System.out.println("e1: hashCode="+ e1.hashCode() + "; getClass()=" + e1.getClass());  
    System.out.println("e2: hashCode="+ e2.hashCode() + "; getClass()=" + e2.getClass());   
    System.out.println("ht1.toString()   =" + ht1);
  }
 
}
 


輸出結果
e1: hashCode=7001; getClass()=class Employee
e2: hashCode=7001; getClass()=class Employee
ht1.toString() ={Employee@1b59=Employee@1b59, Employee@1b59=Employee@1b59}
已經故意讓e1、e2計算hashCode時,都只考慮員編而不考慮姓名了,為什麼還是放得進去?


weberhwang edited on 2018-05-17 04:20
reply to postreply to post
話題樹型展開
人氣 標題 作者 字數 發文時間
524 HashMap關於hashCode()與equals()的問題 weberhwang 211 2018-05-16 01:52
435 Re:HashMap關於hashCode()與equals()的問題 layolayo2002 176 2018-05-16 04:25
450 Re:HashMap關於hashCode()與equals()的問題 weberhwang 235 2018-05-16 04:39
420 Re:HashMap關於hashCode()與equals()的問題 sir_ap 40 2018-05-16 09:06
417 Re:HashMap關於hashCode()與equals()的問題 kentyeh 1825 2018-05-16 12:56
422 Re:HashMap關於hashCode()與equals()的問題 weberhwang 3756 2018-05-17 01:54
379 Re:HashMap關於hashCode()與equals()的問題 sir_ap 757 2018-05-17 07:47
378 Re:HashMap關於hashCode()與equals()的問題 weberhwang 486 2018-05-18 01:05
416 Re:HashMap關於hashCode()與equals()的問題 kentyeh 839 2018-05-18 03:55
» JWorld@TW »  Java 新手區

reply to postflat modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8