Hashtable
不能以null
為key;HashMap
可以null
為key。Hashtable
是執行緒安全的;HashMap
是非執行緒安全的。Hashtable
效能比HashMap
差。因為Hashtable
為執行緒安全,也就是synchronized
的,所以在單執行緒時的效能比非執行緒安全的HashMap
差。
第1點Hashtable
不能以null
為key的範例如下
HashMap<String, String> hm = new HashMap<>();
hm.put(null, "1"); // OK
Hashtable<String, String> ht = new Hashtable<>();
ht.put(null, "1"); // 丟出NullPointerException
關於第二點,對非執行緒安全的HashMap
併行修改(concurrent modification)資料,會發生ConcurrentModificationException
例外,例如執行下面程式時,因為不同的執行緒修改了HashMap<String, String> hm
,所以可能發生錯誤。
HashMap<String, String> hm = new HashMap<>();
for (int i = 0; i < 1000; i++) {
hm.put("key" + i, "value" + i);
}
// 執行緒1, 遍歷印出每個key-value值
Thread t1 = new Thread(() -> {
Iterator<Map.Entry<String, String>> it = hm.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println(entry.getKey() + ":" + entry.getValue());
}
});
// 執行緒2, 增加一個key-value
Thread t2 = new Thread(() -> {
hm.put("key1000", "value1000");
});
t1.start();
t2.start();
錯誤訊息如下
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1442)
at java.util.HashMap$EntryIterator.next(HashMap.java:1476)
at java.util.HashMap$EntryIterator.next(HashMap.java:1474)
at idv.matt.demo.Main.lambda$0(Main.java:25)
at java.lang.Thread.run(Thread.java:748)
不過如果要對Map資料進行多執行續操作,建議使用ConcurrentHashMap
,因為效能優於Hashtable
。
參考:
Hi 想請問如果我將
回覆刪除`HashMap hm = new HashMap<>();`
改成
`HashTable hm = new HashTable<>();` 或
` final Map hm = Collections.synchronizedMap(new HashMap<>());
`
執行這段程式還是會出現ConcurrentModificationException, 跟我想像的不太一樣,請問是哪裡的觀念還需要注意嗎? 謝謝
小丸您好,我試了
回覆刪除Hashtable hm = new Hashtable<>(); 或
ConcurrentHashMap hm = new ConcurrentHashMap();
都沒出現ConcurrentModificationException,可能要再請您試試看。