首頁 > 軟體

Java集合框架之Map詳解

2022-03-03 19:02:48

1、Map的實現

  • HashMap
  • Hashtable
  • LinkedHashMap
  • TreeMap
  • ConcurrentHashMap

2、HashMap 和 Hashtable 的區別

  • HashMap:底層是基於陣列+連結串列實現,非執行緒安全的,預設容量是16、允許有空的健和值
  • Hashtable:基於雜湊表實現,執行緒安全的(加了synchronized鎖),預設容量是11,不允許有空的健和值

3、介紹下物件的 hashCode()和equals(),使用場景

hashCode:

頂級類Object裡面的方法,所有的類都是繼承Object,返回是一個int型別的數

根據一定的hash規則(儲存地址,欄位,長度等),對映成一個數值,即雜湊值

@Override
public int hashCode() {
     return Objects.hash(age,name,time);
}

equals:

頂級類Object裡面的方法,所有的類都是繼承Object,返回是一個boolean型別

根據自定義的匹配規則,用於匹配兩個物件是否一樣,一般邏輯如下:

1、判斷地址是否一樣

2、非空判斷 和 Class型別判斷

3、強轉

4、物件裡面的欄位一一匹配

@Override
public boolean equals(Object obj) {
    if (obj == this)
        return true;
    if (obj == null || getClass() != obj.getClass())
        return false;
    User user = (User) obj;
    return age == user.age && Objects.equals(name, user.name) && Objects.equals(time, user.time);
}

使用場景:物件比較、或者集合容器裡面排重、比較、排序

4、HashMap和TreeMap應該怎麼選擇,使用場景

hashMap:

  • 雜湊桶(陣列+連結串列),可以實現快速的儲存和檢索,但是確實包含無序的元素,適用於在map中插入刪除和定位元素

treeMap:

  • 使用儲存結構是一個平衡二元樹->紅黑樹,可以自定義排序規則,要實現Comparator介面
  • 能便捷的實現內部元素的各種排序,但是一般效能比HashMap差,適用於安裝自然排序或者自定義排序規則 (寫過微信支付簽名工具類就用這個類)

5、Set和Map的關係 TODO

核心就是不儲存重複的元素,儲存一組唯一的物件

set的每一種實現都是對應Map裡面的一種封裝,

HashSet對應的就是HashMap,treeSet對應的就是treeMap

  • set:無序,不允許存在重複的元素
  • list:有序,可以存在重複元素
  • set 和 list 對比: 都是Collection的子介面,Collection是集合類;
  • set 檢查元素效率低下,刪除和插入的效率高,插入和刪除不會引起元素的位置變化;
  • list 和陣列類似,List可以動態增長,查詢元素的效率較高,插入元素和刪除元素效率低,因為會引起其他元素位置發生變化
  • map: Map介面不是Collection介面的繼承,而是從自己的用於維護鍵值對關聯的介面層次結構入手,按定義,該介面描述了從不重複的鍵到值的對映

6、常見Map的排序規則是怎樣的?

按照新增順序使用LinkedHashMap,按照自然排序使用TreeMap,自定義排序 TreeMap(Comparetor c)

7、如果需要執行緒安全,且效率高的Map,應該怎麼做?

  • 多執行緒環境下可以用concurrent包下的ConcurrentHashMap,或者使用Collections.synchronizedMap(),
  • ConcurrentHashMap雖然是執行緒安全,但是他的效率比Hashtable要高很多使用
  • Collections.synchronizedMap包裝後返回的map是加鎖的

8、介紹下 HashMap

  • HashMap底層(陣列+連結串列+紅黑樹 jdk8才有紅黑樹),在JDK1.8中,連結串列的長度大於8,連結串列會轉換成紅黑樹
  • 陣列中每一項是一個連結串列,即陣列和連結串列的結合體
  • Node<K,V>[] table

是陣列,陣列的元素是Entry(Node繼承Entry),Entry元素是一個key-value的鍵值對,它持有一個指向下個Entry的參照,table陣列的每個Entry元素同時也作為當前Entry連結串列的首節點,也指向了該連結串列的下個Entry元素

9、什麼是Hash碰撞?常見的解決辦法有哪些,hashmap採用哪種方法?

  • hash碰撞的意思是不同key計算得到的Hash值相同,需要放到同個bucket中
  • 常見的解決辦法:連結串列法、開發地址法、再雜湊法等
  • HashMap採用的是連結串列法

10、HashMap底層是 陣列+連結串列+紅黑樹,為什麼要用這幾類結構呢?

  • 陣列:Node<K,V>[] table ,根據物件的key的hash值確定在陣列裡面是哪個節點 - 連結串列:作用是解決hash衝突,將hash值一樣的物件存在一個連結串列放在hash值對應的槽位
  • 紅黑樹:JDK8使用紅黑樹來替代超過8個節點的連結串列,主要是查詢效能的提升,從原來的O(n)到O(logn),
  • 通過hash碰撞,讓HashMap不斷產生碰撞,那麼相同key的位置的連結串列就會不斷增長,
  • 當對這個Hashmap的相應位置進行查詢的時候,就會迴圈遍歷這個超級大的連結串列,效能就會下降,所以改用紅黑樹

11、為什麼選擇紅黑樹而不用其他樹,比如二叉查詢樹,為什麼不一直開始就用紅黑樹,而是到8的長度後才變換

  • 二叉查詢樹在特殊情況下也會變成一條線性結構,和原先的連結串列存在一樣的深度遍歷問題,查詢效能就會慢,
  • 使用紅黑樹主要是提升查詢資料的速度,紅黑樹是平衡二元樹的一種,插入新資料後會通過左旋,右旋、變色等操作來保持平衡,解決單連結串列查詢深度的問題
  • 資料量少的時候運算元據,遍歷線性表比紅黑樹所消耗的資源少,且前期資料少平衡二元樹保持平衡是需要消耗資源的,所以前期採用線性表,等到一定數之後變換到紅黑樹

12、瞭解ConcurrentHashMap嗎?為什麼效能比hashtable高,說下原理

  • ConcurrentHashMap是執行緒安全的Map,因為hashtable類基本上所有的方法都是採用synchronized進行執行緒安全控制,高並行情況下效率就降低
  • ConcurrentHashMap是採用了分段鎖的思想提高效能,鎖粒度更細化

13、jdk1.7和jdk1.8裡面ConcurrentHashMap實現的區別有沒了解

  • JDK8之前,ConcurrentHashMap使用鎖分段技術,將資料分成一段段儲存,每個資料段設定一把鎖,即segment類,這個類繼承ReentrantLock來保證執行緒安全 【技術點:Segment + HashEntry】
  • JKD8的版本取消Segment這個分段鎖資料結構,底層也是使用Node陣列+連結串列+紅黑樹,從而實現對每一段資料就行加鎖,也減少了並行衝突的概率,CAS(讀)+Synchronized(寫)【技術點:Node + Cas + Synchronized】

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!   


IT145.com E-mail:sddin#qq.com