最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?集合框架底層數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)深度解析(示例詳解)

 更新時(shí)間:2025年06月20日 08:48:46   作者:晴空月明  
Java 集合框架(Java Collections Framework, JCF)是支撐高效數(shù)據(jù)處理的核心組件,其底層數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)直接影響性能與適用場(chǎng)景,這篇文章主要介紹Java集合框架底層數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)深度解析,需要的朋友可以參考下

Java 集合框架(Java Collections Framework, JCF)是支撐高效數(shù)據(jù)處理的核心組件,其底層數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)直接影響性能與適用場(chǎng)景。本文從線性集合、集合、映射三大體系出發(fā),系統(tǒng)解析ArrayListLinkedList、HashMap、TreeSet等核心類的底層實(shí)現(xiàn)原理,結(jié)合 JDK 版本演進(jìn)與工程實(shí)踐,確保內(nèi)容深度與去重性,助力面試者構(gòu)建系統(tǒng)化知識(shí)體系。

線性集合(List):順序存儲(chǔ)與鏈?zhǔn)浇Y(jié)構(gòu)的權(quán)衡

動(dòng)態(tài)數(shù)組實(shí)現(xiàn):ArrayList

底層結(jié)構(gòu)

  • 核心數(shù)據(jù)
    • 基于Object[] elementData數(shù)組存儲(chǔ)元素,通過modCount記錄結(jié)構(gòu)性修改次數(shù)(fail-fast 機(jī)制)。
    • 擴(kuò)容策略:當(dāng)元素?cái)?shù)量超過threshold(默認(rèn)elementData.length * 0.75),按oldCapacity + (oldCapacity >> 1)(1.5 倍)擴(kuò)容,調(diào)用Arrays.copyOf()復(fù)制數(shù)組。

核心方法實(shí)現(xiàn)

  • 添加元素(add (E e)) :
public boolean add(E e) {  
   ensureCapacityInternal(size + 1);  // 檢查擴(kuò)容 
   elementData[size++] = e; 
   return true; 
}
  • 均攤時(shí)間復(fù)雜度O(1) (忽略擴(kuò)容開銷),擴(kuò)容時(shí)為 O(n) 。

  • 隨機(jī)訪問(get (int index)) :
    直接通過數(shù)組下標(biāo)訪問,時(shí)間復(fù)雜度 O(1) ,優(yōu)于鏈表結(jié)構(gòu)。

優(yōu)缺點(diǎn)與場(chǎng)景

  • 優(yōu)點(diǎn):隨機(jī)訪問高效,內(nèi)存連續(xù)存儲(chǔ)提升 CPU 緩存利用率。
  • 缺點(diǎn):插入 / 刪除(非尾部)需移動(dòng)元素,平均O(n) ;擴(kuò)容產(chǎn)生額外開銷。
  • 適用場(chǎng)景:頻繁隨機(jī)訪問、元素?cái)?shù)量可預(yù)估的場(chǎng)景(如數(shù)據(jù)報(bào)表生成)。

雙向鏈表實(shí)現(xiàn):LinkedList

底層結(jié)構(gòu)

  • 核心數(shù)據(jù)
    • Node<E>節(jié)點(diǎn)組成雙向鏈表,每個(gè)節(jié)點(diǎn)包含prev、next指針及item值。
    • 頭尾指針first、last優(yōu)化邊界操作,無容量限制。

核心方法實(shí)現(xiàn)

  • 添加元素(add (E e)) :
void linkLast(E e) { 
   Node<E> l = last; 
   Node<E> newNode = new Node<>(l, e, null); 
   last = newNode; 
   if (l == null) 
       first = newNode; 
   else 
       l.next = newNode; 
   size++; 
   modCount++; 
} 
  • 尾部添加時(shí)間復(fù)雜度O(1) ,頭部 / 中間添加需定位節(jié)點(diǎn)(O(n) )。

  • 刪除元素(remove (Object o)) :
    遍歷鏈表查找元素,修改前后節(jié)點(diǎn)指針,時(shí)間復(fù)雜度O(n) 。

優(yōu)缺點(diǎn)與場(chǎng)景

  • 優(yōu)點(diǎn):任意位置插入 / 刪除高效(僅需指針操作),內(nèi)存動(dòng)態(tài)分配無擴(kuò)容開銷。
  • 缺點(diǎn):隨機(jī)訪問需遍歷鏈表(O(n) ),內(nèi)存非連續(xù)導(dǎo)致緩存命中率低。
  • 適用場(chǎng)景:頻繁插入 / 刪除(如隊(duì)列、棧場(chǎng)景),元素?cái)?shù)量動(dòng)態(tài)變化大。

集合(Set):唯一性與有序性的實(shí)現(xiàn)

哈希表實(shí)現(xiàn):HashSet

底層結(jié)構(gòu)

  • 本質(zhì):基于HashMap實(shí)現(xiàn),元素作為HashMap的鍵,值統(tǒng)一為PRESENT(靜態(tài)占位對(duì)象)。
  • 哈希沖突處理
    • JDK 1.8 前:數(shù)組 + 鏈表,沖突元素以鏈表形式存儲(chǔ)在數(shù)組桶中。
    • JDK 1.8 后:引入紅黑樹,當(dāng)鏈表長度≥8 且數(shù)組長度≥64 時(shí),鏈表轉(zhuǎn)換為紅黑樹,提升查找效率(O(log n) )。

核心特性

  • 唯一性:利用HashMap鍵的唯一性,通過key.equals()key.hashCode()保證元素不重復(fù)。
  • 無序性:元素順序由哈希值決定,遍歷時(shí)按哈希桶順序訪問。

與 HashMap 的關(guān)聯(lián)

public class HashSet<E> { 
   private transient HashMap<E, Object> map; 
   private static final Object PRESENT = new Object(); 
   public HashSet() { 
       map = new HashMap<>(); 
   } 
   public boolean add(E e) { 
       return map.put(e, PRESENT) == null; 
   } 
} 

有序集合:TreeSet

底層結(jié)構(gòu)

  • 本質(zhì):基于TreeMap實(shí)現(xiàn),元素作為TreeMap的鍵,值同樣為占位對(duì)象。
  • 數(shù)據(jù)結(jié)構(gòu):紅黑樹(自平衡二叉搜索樹),確保元素按自然順序(Comparable)或定制順序(Comparator)排序。

核心特性

  • 有序性:中序遍歷紅黑樹實(shí)現(xiàn)升序排列,first()、last()等方法時(shí)間復(fù)雜度O(1) 。
  • 唯一性:依賴紅黑樹節(jié)點(diǎn)的唯一性,重復(fù)元素通過比較器判定后拒絕插入。

性能對(duì)比

操作HashSet (HashMap)TreeSet (TreeMap)
添加 / 刪除O (1)(均攤)O(log n)
有序遍歷無序O (n)(中序遍歷)
范圍查詢不支持O (log n)(如 headSet ())

映射(Map):鍵值對(duì)存儲(chǔ)的核心實(shí)現(xiàn)

哈希映射:HashMap

底層結(jié)構(gòu)(JDK 1.8+)

  • 數(shù)組 + 鏈表 + 紅黑樹
    • Node<K,V>[] table:哈希桶數(shù)組,初始容量 16,負(fù)載因子 0.75。
    • 哈希沖突時(shí),JDK 1.7 采用頭插法(多線程可能形成環(huán)),1.8 改用尾插法并引入紅黑樹(鏈表長度≥8 且數(shù)組長度≥64 時(shí)轉(zhuǎn)換)。

核心方法實(shí)現(xiàn)(put (K key, V value))

  • 計(jì)算哈希值:通過key.hashCode()異或高位((h = key.hashCode()) ^ (h >>> 16))減少哈希碰撞。
  • 定位桶位置table[i = (n - 1) & hash],其中n為數(shù)組長度(必須是 2 的冪)。
  • 處理沖突
  • 若桶為空,直接插入新節(jié)點(diǎn)。
  • 若桶為紅黑樹,按紅黑樹規(guī)則插入。
  • 若桶為鏈表,遍歷鏈表:
    • 存在相同鍵則替換值;
    • 鏈表長度≥7 時(shí)(閾值 8-1),觸發(fā)樹化(treeifyBin())。
  • 擴(kuò)容:元素?cái)?shù)量size > thresholdcapacity * loadFactor)時(shí),按 2 倍擴(kuò)容并重新哈希,時(shí)間復(fù)雜度O(n) 。

線程安全問題

  • 非線程安全,多線程并發(fā)修改可能導(dǎo)致數(shù)據(jù)丟失或死循環(huán)(JDK 1.7 頭插法環(huán)問題,1.8 尾插法避免環(huán)但仍需同步)。
  • 線程安全替代:ConcurrentHashMap(分段鎖→CAS + 紅黑樹)、Hashtable(全表鎖,性能低下)。

有序映射:TreeMap

底層結(jié)構(gòu)

  • 紅黑樹實(shí)現(xiàn):每個(gè)節(jié)點(diǎn)存儲(chǔ)鍵值對(duì),通過compareTo()Comparator確定節(jié)點(diǎn)位置,保證中序遍歷有序。
  • 節(jié)點(diǎn)結(jié)構(gòu)
static final class Entry<K,V> implements Map.Entry<K,V> { 
   K key; 
   V value; 
   Entry<K,V> left, right; 
   int color; 
   // 紅黑樹節(jié)點(diǎn)屬性(color、父節(jié)點(diǎn)等) 
} 

核心特性

  • 有序性:支持范圍查詢(如subMap(k1, k2)),時(shí)間復(fù)雜度O(log n) 。
  • 穩(wěn)定性:紅黑樹的平衡策略(最多黑高差 1)確保查找、插入、刪除均攤O(log n) 。

適用場(chǎng)景

  • 需要鍵有序遍歷、范圍查詢的場(chǎng)景(如字典序排序、時(shí)間序列數(shù)據(jù)存儲(chǔ))。

高效并發(fā)映射:ConcurrentHashMap

底層結(jié)構(gòu)演進(jìn)

  • JDK 1.7:分段鎖(Segment數(shù)組,每個(gè)Segment是獨(dú)立的哈希表,鎖粒度為段)。
  • JDK 1.8:CAS+ synchronized(鎖粒度細(xì)化到哈希桶,鏈表 / 紅黑樹節(jié)點(diǎn)),取消Segment,提升并發(fā)度。

核心實(shí)現(xiàn)(JDK 1.8+)

  • 數(shù)組 + 鏈表 + 紅黑樹:與 HashMap 類似,但節(jié)點(diǎn)支持并發(fā)訪問:

    • 鏈表節(jié)點(diǎn)用volatile修飾next指針,保證可見性。
    • 紅黑樹節(jié)點(diǎn)通過synchronized控制寫操作,讀操作無鎖(利用 volatile 和 CAS)。
  • 擴(kuò)容機(jī)制

    • 采用分段擴(kuò)容(transfer()方法),允許多線程參與擴(kuò)容,通過ForwardingNode標(biāo)記遷移中的桶。

線程安全保障

  • 寫操作:通過synchronized鎖定單個(gè)桶,避免全表鎖。
  • 讀操作:無鎖,通過volatile保證可見性,結(jié)合 CAS 實(shí)現(xiàn)無阻塞讀。

隊(duì)列(Queue):不同場(chǎng)景下的高效存取

雙向隊(duì)列:LinkedList(實(shí)現(xiàn) Queue 接口)

底層結(jié)構(gòu)

  • 基于雙向鏈表,實(shí)現(xiàn)offer()、poll()、peek()等隊(duì)列操作:
    • offer(E e):尾插法,時(shí)間復(fù)雜度O(1) 。
    • poll():頭節(jié)點(diǎn)刪除,時(shí)間復(fù)雜度O(1) 。

適用場(chǎng)景

  • 實(shí)現(xiàn) FIFO 隊(duì)列(如任務(wù)調(diào)度)、雙端隊(duì)列(Deque 接口支持頭尾操作)。

優(yōu)先隊(duì)列:PriorityQueue

底層結(jié)構(gòu)

  • 堆結(jié)構(gòu):基于動(dòng)態(tài)數(shù)組實(shí)現(xiàn)的二叉堆(默認(rèn)小根堆),元素按自然順序或定制比較器排序。
  • 堆性質(zhì):父節(jié)點(diǎn)值≤子節(jié)點(diǎn)值(小根堆),通過shiftUp()shiftDown()維護(hù)堆序。

核心操作

  • 插入(offer (E e)) :尾插后向上調(diào)整堆,時(shí)間復(fù)雜度O(log n) 。
  • 刪除(poll ()) :刪除根節(jié)點(diǎn)后向下調(diào)整堆,時(shí)間復(fù)雜度O(log n) 。

適用場(chǎng)景

  • 任務(wù)優(yōu)先級(jí)調(diào)度(如線程池中的任務(wù)隊(duì)列)、Top-N 問題(維護(hù)大小為 N 的堆)。

面試高頻問題深度解析

數(shù)據(jù)結(jié)構(gòu)對(duì)比問題

Q:ArrayList 與 LinkedList 的適用場(chǎng)景差異?

A:

  • ArrayList:適合隨機(jī)訪問(O (1)),插入 / 刪除尾部元素高效,適合數(shù)據(jù)量可預(yù)估、頻繁讀取的場(chǎng)景(如報(bào)表生成)。
  • LinkedList:適合任意位置插入 / 刪除(O (1) 指針操作),內(nèi)存動(dòng)態(tài)分配,適合頻繁修改、數(shù)據(jù)量不確定的場(chǎng)景(如隊(duì)列、棧)。

Q:HashMap 與 Hashtable 的核心區(qū)別?

A:

維度HashMapHashtable
線程安全非線程安全線程安全(全表 synchronized)
null 鍵值允許 null 鍵 / 值不允許 null
性能更高(無鎖開銷)低(鎖粒度粗)
迭代器fail-fast 機(jī)制安全失敗(clone 數(shù)組遍歷)

底層實(shí)現(xiàn)細(xì)節(jié)問題

Q:HashMap 如何解決哈希沖突?JDK 1.8 的優(yōu)化點(diǎn)是什么?

A:

  • 沖突解決:鏈地址法(數(shù)組 + 鏈表),JDK 1.8 引入紅黑樹優(yōu)化長鏈表(鏈表長度≥8 且數(shù)組長度≥64 時(shí)轉(zhuǎn)換為紅黑樹,查找時(shí)間從 O (n) 降至 O (log n))。

  • 優(yōu)化點(diǎn)

  • 尾插法替代頭插法,避免多線程環(huán)問題;

  • 紅黑樹提升長鏈表操作效率;

  • 擴(kuò)容時(shí)采用哈希高位運(yùn)算減少碰撞。

Q:為什么 ConcurrentHashMap 在 JDK 1.8 后放棄分段鎖?

A:

  • 分段鎖(Segment)的鎖粒度仍較大(默認(rèn) 16 個(gè)段),并發(fā)度受限于段數(shù)量。
  • JDK 1.8 改用 CAS+synchronized 鎖定單個(gè)哈希桶,鎖粒度細(xì)化到節(jié)點(diǎn),提升并發(fā)度(理論并發(fā)度為桶數(shù)量),同時(shí)利用紅黑樹優(yōu)化長鏈表性能。

性能優(yōu)化問題

Q:如何提升 HashMap 的性能?

A:

  • 預(yù)估算容量:通過HashMap(int initialCapacity)指定初始容量,避免多次擴(kuò)容(如已知元素?cái)?shù)量 1000,初始容量設(shè)為ceil(1000/0.75)=1334,取最近 2 的冪 16384)。

  • 優(yōu)化哈希函數(shù):重寫hashCode()時(shí)確保散列均勻(如 String 的哈希算法混合高低位)。

  • 利用紅黑樹:當(dāng)元素分布不均勻時(shí),確保數(shù)組長度≥64,觸發(fā)樹化提升查找效率。

總結(jié):數(shù)據(jù)結(jié)構(gòu)選擇的三維度

功能需求

  • 有序性:需要排序選TreeSet/TreeMap,無序高頻查找選HashSet/HashMap。
  • 唯一性Set接口保證元素唯一,Map接口保證鍵唯一。
  • 線程安全:并發(fā)場(chǎng)景選ConcurrentHashMap(細(xì)粒度鎖),而非過時(shí)的Hashtable。

性能特征

  • 時(shí)間復(fù)雜度

    • 隨機(jī)訪問:ArrayList(O(1))vs LinkedList(O(n))。
    • 插入 / 刪除:鏈表(O (1) 指針操作)vs 數(shù)組(O (n) 元素移動(dòng))。
    • 查找:HashMap(均攤 O (1))vs TreeMap(O(log n))。
  • 空間復(fù)雜度:鏈表(每個(gè)節(jié)點(diǎn)額外指針)vs 數(shù)組(連續(xù)內(nèi)存,無額外開銷)。

工程實(shí)踐

  • 避免默認(rèn)初始化:大數(shù)量級(jí)元素時(shí)指定初始容量,減少擴(kuò)容開銷(如new ArrayList<>(1000))。

  • 優(yōu)先使用接口:聲明為List/Map而非具體實(shí)現(xiàn)類,提升代碼可維護(hù)性(如List<String> list = new ArrayList<>())。

  • 注意 fail-fast 機(jī)制:迭代器遍歷時(shí)修改集合可能拋出ConcurrentModificationException,并發(fā)場(chǎng)景用ConcurrentHashMapkeySet()values()

通過深入理解集合框架的底層數(shù)據(jù)結(jié)構(gòu),面試者可根據(jù)具體場(chǎng)景選擇最優(yōu)實(shí)現(xiàn),同時(shí)在回答中結(jié)合 JDK 版本演進(jìn)(如 HashMap 的紅黑樹優(yōu)化、ConcurrentHashMap 的鎖升級(jí))展現(xiàn)技術(shù)深度。掌握數(shù)據(jù)結(jié)構(gòu)的核心原理與性能特征,是應(yīng)對(duì)高級(jí)程序員面試中集合相關(guān)問題的關(guān)鍵。

到此這篇關(guān)于Java 集合框架底層數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)深度解析的文章就介紹到這了,更多相關(guān)Java 集合框架底層數(shù)據(jù)結(jié)構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • hibernate4快速入門實(shí)例詳解

    hibernate4快速入門實(shí)例詳解

    Hibernate是一個(gè)輕量級(jí)的ORMapping框架,本文重點(diǎn)給大家介紹hibernate4 入門實(shí)例詳細(xì),需要的朋友參考下吧
    2017-09-09
  • Java BeanPostProcessor與BeanFactoryPostProcessor基礎(chǔ)使用講解

    Java BeanPostProcessor與BeanFactoryPostProcessor基礎(chǔ)使用講解

    這篇文章主要介紹了Java BeanPostProcessor與BeanFactoryPostProcessor基礎(chǔ)使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • 面試Spring中的bean線程是否安全及原因

    面試Spring中的bean線程是否安全及原因

    這篇文章主要為大家介紹了面試中常問的Spring中bean線程是否安全及原因,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • Java中異或的深入講解

    Java中異或的深入講解

    這篇文章主要給大家介紹了關(guān)于Java中異或的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • MyEclipse配置JDK的全過程

    MyEclipse配置JDK的全過程

    這篇文章主要介紹了MyEclipse配置JDK的全過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 詳解Spring Security中權(quán)限注解的使用

    詳解Spring Security中權(quán)限注解的使用

    這篇文章主要為大家詳細(xì)介紹一下Spring Security中權(quán)限注解的使用方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以參考一下
    2022-05-05
  • 執(zhí)行java請(qǐng)求時(shí)導(dǎo)致在腳本執(zhí)行結(jié)束時(shí)JVM無法退出

    執(zhí)行java請(qǐng)求時(shí)導(dǎo)致在腳本執(zhí)行結(jié)束時(shí)JVM無法退出

    這篇文章主要介紹了執(zhí)行java請(qǐng)求,導(dǎo)致在腳本執(zhí)行結(jié)束時(shí)JVM無法退出問題,本文通過原因分析給出解決方案,需要的朋友可以參考下
    2020-02-02
  • Spring?Security方法級(jí)安全控制@PreAuthorize注解的靈活運(yùn)用小結(jié)

    Spring?Security方法級(jí)安全控制@PreAuthorize注解的靈活運(yùn)用小結(jié)

    本文將帶著大家講解?@PreAuthorize?注解的核心原理、SpEL?表達(dá)式機(jī)制,并通過的示例代碼演示如何在實(shí)際項(xiàng)目中靈活運(yùn)用該注解實(shí)現(xiàn)細(xì)粒度的權(quán)限控制,感興趣的朋友一起看看吧
    2025-04-04
  • Netty之使用DelimiterBasedFrameDecoder進(jìn)行消息分隔詳解

    Netty之使用DelimiterBasedFrameDecoder進(jìn)行消息分隔詳解

    這篇文章主要介紹了Netty之使用DelimiterBasedFrameDecoder進(jìn)行消息分隔詳解,在使用Netty進(jìn)行TCP消息傳輸時(shí),為了上層協(xié)議能夠?qū)ο⒄_區(qū)分,避免粘包和拆包導(dǎo)致的問題,一般可以通過消息定長、將回車換行符作為消息結(jié)束符,需要的朋友可以參考下
    2023-12-12
  • Java8中forEach語句循環(huán)一個(gè)List和Map

    Java8中forEach語句循環(huán)一個(gè)List和Map

    這篇文章主要給大家介紹了關(guān)于Java8中forEach語句循環(huán)一個(gè)List和Map的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02

最新評(píng)論

江陵县| 博白县| 彭州市| 临泉县| 水富县| 密云县| 牡丹江市| 建湖县| 汝州市| 岱山县| 古丈县| 勃利县| 平安县| 会泽县| 三都| 景东| 北流市| 平南县| 彭水| 张家界市| 灌南县| 秦皇岛市| 孝感市| 柘荣县| 萨嘎县| 临朐县| 旺苍县| 芦溪县| 普宁市| 那坡县| 桂阳县| 正宁县| 福清市| 乌兰县| 江源县| 寿光市| 隆安县| 西吉县| 新乡市| 龙州县| 当涂县|