1. 程式人生 > >集合框架——HashMap和Hashtable

集合框架——HashMap和Hashtable

兩者區別:

1.Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現。

2.HashMap允許將null作為一個entry的key或者value,而Hashtable不允許。

3.HashMap是非synchronized,而Hashtable是synchronized,這意味著Hashtable是執行緒安全的,多個執行緒可以共享一個Hashtable;而如果沒有正確的同步的話,多個執行緒是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴充套件性更好。(在多個執行緒訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap 就必須為之提供外同步(Collections.synchronizedMap))

4.另一個區別是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以當有其它執行緒改變了HashMap的結構(增加或者移除元素),將會丟擲ConcurrentModificationException,但迭代器本身的remove()方法移除元素則不會丟擲ConcurrentModificationException異常。但這並不是一個一定發生的行為,要看JVM。這條同樣也是Enumeration和Iterator的區別。fail-fast機制如果不理解原理,可以檢視這篇文章:http://www.cnblogs.com/alexlo/archive/2013/03/14/2959233.html

5.由於HashMap非執行緒安全,在只有一個執行緒訪問的情況下,效率要高於HashTable。

6.HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。 

7.Hashtable中hash陣列預設大小是11,增加的方式是 old*2+1。HashMap中hash陣列的預設大小是16,而且一定是2的指數。

8..兩者通過hash值雜湊到hash表的演算法不一樣

自定義類作為Key值時需要注意的問題:

1、如果是根據物件的相關屬性來自定義物件相等的邏輯,需要重寫equals()方法,一旦重寫equals()就必須重寫hashcode()

2、當自定義類的多項作為HashMap(Hashtable)的key時,最好把這個類設計為不可變類

3、從HashMap的工作原理可以看出,如果兩個物件相等,那麼這兩個物件有著相同的hashcode,反之不成立。

有如下幾種方法:

1. 通過keyset

2. 通過 Map.entrySet().iterator()

3. 通過foreach ---- Map.entryset, 當hashmap很大時,推薦使用這種方式。

4. 通過Valueset

public static void main(String[] args) {
        HashMap<Integer, String> hashmap = new HashMap<>();
        hashmap.put(1,"gogo");
        hashmap.put(2,"wade");
        hashmap.put(3,"james");
        hashmap.put(4,"curry");
        // 1. 通過Map.keySet遍歷key和value:
        for (int key : hashmap.keySet()){
            System.out.println("key: "+ key + "; value: " + hashmap.get(key));
        }
 
        //2. 通過Map.entrySet使用iterator遍歷key和value:
        Iterator<Map.Entry<Integer, String>> it = hashmap.entrySet().iterator();
        while (it.hasNext()){
            Map.Entry<Integer, String> entry = it.next();
            System.out.println("key: "+ entry.getKey() + "; value: " + entry.getValue());
        }
 
        //3. 通過Map.entrySet遍歷key和value
        for(Map.Entry<Integer, String> entry : hashmap.entrySet()){
            System.out.println("key: "+ entry.getKey() + "; value: " + entry.getValue());
        }
 
        //4. 通過Map.values()遍歷所有的value,但不能遍歷key
        for (String value : hashmap.values()) {
            System.out.println("value: "+value);
        }
    }