ADT基礎(三)—— HashMap

iterationjia發表於2021-02-28

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,避免重複計算
    }
    
    ADT基礎(三)——  HashMap
    • 簡單來說,HashMap由陣列+連結串列組成的,陣列是HashMap的主體,連結串列則是主要為了解決雜湊衝突而存在的。
      • 如果定位到的陣列位置不含連結串列(當前entry的next指向null),那麼查詢,新增等操作很快,僅需一次定址即可
      • 如果定位到的陣列包含連結串列。
        • 對於新增操作,其時間複雜度為O(n),首先遍歷連結串列,存在即覆蓋,否則新增;
        • 對於查詢操作來講,仍需遍歷連結串列,然後通過key物件的equals方法逐一比對查詢。所以,效能考慮,HashMap中的連結串列出現越少,效能才會越好。
    • 其他內容,如put,get原理下次補充,參考博文

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;

相關文章