ADT基礎(三)—— HashMap
1 雜湊表
- 雜湊表(hash table),也叫雜湊表,是一種非常重要的資料結構,應用場景及其豐富,許多快取技術(比如memcached)的核心其實就是在記憶體中維護一張大的雜湊表。
- 在雜湊表中進行新增,刪除,查詢等操作,效能十分之高,不考慮雜湊衝突的情況下(後面會探討下雜湊衝突的情況),僅需一次定位即可完成,時間複雜度為O(1)。
- 儲存位置 = f(關鍵字) ,這個函式f一般稱為雜湊函式,這個函式的設計好壞會直接影響到雜湊表的優劣。好的雜湊函式會盡可能地保證計算簡單和雜湊地址分佈均勻。
- 插入操作,利用雜湊函式計算儲存位置存入。
- 查詢同理,通過雜湊函式計算實際儲存地址,然後從陣列對應地址取出即可。
2 雜湊衝突
- 如果兩個不同的元素,通過雜湊函式得出的實際儲存地址相同怎麼辦
- 當我們對某個元素進行雜湊運算,得到一個儲存地址,然後要進行插入的時候,發現已經被其他元素佔用了,其實這就是所謂的雜湊衝突,也叫雜湊碰撞。
- 雜湊衝突的解決方案有多種:
- 開放定址法(發生衝突,繼續尋找下一塊未被佔用的儲存地址)
- 再雜湊函式法
- 鏈地址法(HashMap採用),也就是陣列+連結串列的方式。
3 HashMap的實現原理
-
HashMap的主幹是一個Entry陣列。Entry是HashMap的基本組成單元,每一個Entry包含一個key-value鍵值對。
static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next;//儲存指向下一個Entry的引用,單連結串列結構 int hash;//對key的hashcode值進行hash運算後得到的值,儲存在Entry,避免重複計算 }
- 簡單來說,HashMap由陣列+連結串列組成的,陣列是HashMap的主體,連結串列則是主要為了解決雜湊衝突而存在的。
- 如果定位到的陣列位置不含連結串列(當前entry的next指向null),那麼查詢,新增等操作很快,僅需一次定址即可
- 如果定位到的陣列包含連結串列。
- 對於新增操作,其時間複雜度為O(n),首先遍歷連結串列,存在即覆蓋,否則新增;
- 對於查詢操作來講,仍需遍歷連結串列,然後通過key物件的equals方法逐一比對查詢。所以,效能考慮,HashMap中的連結串列出現越少,效能才會越好。
- 其他內容,如put,get原理下次補充,參考博文
- 簡單來說,HashMap由陣列+連結串列組成的,陣列是HashMap的主體,連結串列則是主要為了解決雜湊衝突而存在的。
4 HashMap使用
Map< String, String> map = new HashMap<>();
map.put("aa", "@sohu.com");
map.put("bb","@163.com"); //map.put(k,v);
value = map.get("bb"); //map.get(key);
//通過Map.keySet遍歷
for (String key : map.keySet()) value = map.get(key);
//通過Map.entrySet遍歷
for(Map.Entry<String, String> entry : map.entrySet()){
entry.getKey();
entry.getValue());
}
//通過Map.values()遍歷所有的value
for(String v : map.values()) v;