我們一直知道HashMap是非線程安全的,HashTable是線程安全的,可這是為什么呢?先聊聊HashMap吧,想要了解它為什么是非線程安全的,我們得從它的原理著手。
jdk7中的HashMap
HashMap底層維護(hù)一個(gè)數(shù)組,數(shù)組中的每一項(xiàng)都是Entry
transient Entry<K,V>[] table;
我們向HashMap放置的對(duì)象實(shí)際上是放置在Entry數(shù)組中
而Map中的key、value則以Entry的形式存放在數(shù)組中
private static class Entry<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Entry<K,V> next;
而這個(gè)Entry應(yīng)該放在數(shù)組的哪一個(gè)位置上(這個(gè)位置通常稱為位桶或者h(yuǎn)ash桶,即hash值相同的Entry會(huì)放在同一位置,用鏈表相連),是通過(guò)key的hashCode來(lái)計(jì)算的。
當(dāng)兩個(gè)key通過(guò)hashcode計(jì)算是相同的時(shí)候,就會(huì)發(fā)生hash沖突,HashMap解決hash沖突的辦法是使用鏈表。
簡(jiǎn)而言之就是,如果該位置沒(méi)有對(duì)象,則將對(duì)象直接放到數(shù)組中,如果該位置有對(duì)象,順著存在此對(duì)象的鏈找(Map中不允許存在相同的key和value),如果不存在相同的,第一種情況:如果該鏈表擴(kuò)容了,則把對(duì)象放入到數(shù)組中,原先存放在數(shù)組中的數(shù)據(jù)放置該對(duì)象的后面。第二種情況:如果該鏈表沒(méi)有擴(kuò)容,則直接放到鏈表的最后。如果存在相同的,則進(jìn)行替換。