HashMap簡述
在JDK中,HashMap是存儲鍵值對用的比較多的一個(gè)類。
其基于哈希散列表計(jì)算位置來達(dá)到鍵不重復(fù)存儲。
其內(nèi)部數(shù)據(jù)結(jié)構(gòu)是數(shù)組(散列桶)+鏈表+紅黑樹,
數(shù)組是基礎(chǔ)存儲,存儲位置為計(jì)算出來的hash值和數(shù)組長度減一相與,而數(shù)組長度一直都為2的整數(shù)冪。
鏈表是遇到哈希碰撞時(shí),即數(shù)組同一下標(biāo)要存放第二個(gè)值的時(shí)候,會在原值后面鏈接上下一個(gè)鍵值對。
紅黑樹是在鏈表過長(默認(rèn)大于8)時(shí)進(jìn)行的結(jié)構(gòu)重組,將鏈表轉(zhuǎn)換為紅黑樹,加快搜索效率。
HashMap的聲明
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
擴(kuò)展Map接口代表這個(gè)類是存儲鍵值對的數(shù)據(jù)結(jié)構(gòu)。
HashMap的域
在以往的版本中,是用Entry<K,V>來表示一個(gè)鍵值對結(jié)點(diǎn)的,而后來引入了紅黑樹表示的節(jié)點(diǎn)(TreeNode),就產(chǎn)生了新的表示方法(Node)。
Node
fields
HashMap的構(gòu)造方法
constructors
除了參數(shù)為Map的構(gòu)造方法,其余的都是參數(shù)檢測和默認(rèn)賦值,
另外值得一提的是,傳入initCapacity的構(gòu)造方法都會先將其放入threshold中,
可以發(fā)現(xiàn)構(gòu)造方法中并沒有構(gòu)建任何數(shù)據(jù)結(jié)構(gòu),這些會在第一次put中才會生成。
參數(shù)為Map的構(gòu)造方法調(diào)用了另外的核心方法,后面再詳細(xì)敘述。
HashMap的關(guān)鍵方法
介紹增刪改查之前,先介紹有關(guān)size的方法,也就是table大小的設(shè)定。
resize方法除了初始化會使用,在擴(kuò)容的時(shí)候也會使用,但也同樣保證了是2次冪。
size
put
putAll
get
remove
clear
在JDK1.8中還增加了一些關(guān)于“默認(rèn)值“和”指定值”增刪改查的功能,在這里不再詳細(xì)分析,
只給出方法簽名和用處,代碼本身也比較簡單,感興趣的可以自己去了解一下。
jdk1.8
HashMap的遍歷
Map和LIst不同,因?yàn)镸ap有兩個(gè)泛型參數(shù),所以進(jìn)行遍歷的時(shí)候一個(gè)迭代器不能滿足所有迭代需求,
熟悉HashMap的同學(xué)應(yīng)該知道,JDK提供了3個(gè)便于我們訪問的方法,而其返回的對應(yīng)是3個(gè)集合。
這3個(gè)方法是values(),keySet(),EntrySet()。
從命名和Map我們都可以知道,后兩個(gè)是不能重復(fù)的Set,而第一個(gè)只是Collection,
更值得一提的是,他們都是HashMap的內(nèi)部類,在這里只用EntrySet()來舉例,其他兩個(gè)都差不多甚至更簡單。
entrySet
可能有的同學(xué)會問了,為什么不用Node<K,V>而要用Entry<K,V>呢,搞的還要轉(zhuǎn)換。
因?yàn)橹鞍姹径际怯玫腅ntry,突然改成Node會使很多代碼要重寫,不太合適,而且Entry在遍歷的時(shí)候已經(jīng)足夠使用。
遍歷的時(shí)候仍是采取了迭代器的方式。
EntryIterator
可以發(fā)現(xiàn),EntrySet的迭代器和HashMap中數(shù)據(jù)內(nèi)容是息息相關(guān)的,
也就是說是互相影響的,這也是HashMap不能在多線程使用的原因之一。
http://www.cnblogs.com/bhbcsc/p/7143141.html