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

不僅僅是?HashMap:盤點(diǎn)?Java?中?O(1)?的鍵值對存儲利器

 更新時間:2026年06月15日 09:28:32   作者:這就是佬們嗎  
本文詳細(xì)解析了限流的必要性、固定窗口與滑動窗口算法原理及應(yīng)用場景,通過對比分析三種限流算法(固定窗口、滑動窗口、令牌桶),并提供了基于Redis的分布式滑動窗口限流實現(xiàn)方案,幫助你全面掌握限流技術(shù)

在 Java 開發(fā)中,當(dāng)你需要一個能以 O ( 1 ) O(1) O(1) 時間復(fù)雜度進(jìn)行快速查找和寫入的數(shù)據(jù)結(jié)構(gòu)時,99% 的開發(fā)者腦海中閃過的第一個詞絕對是:HashMap。

作為 Java 集合框架中最閃耀的明星,HashMap 確實是我們在絕大多數(shù)場景下的不二之選。但是,它真的是任何情況下的“最優(yōu)解”嗎?如果在多線程高并發(fā)環(huán)境下呢?如果我們需要按順序遍歷呢?如果我們的 Key 是一些極其特殊的類型(比如枚舉或連續(xù)的小整數(shù)),還有沒有比 HashMap 更快、更節(jié)省內(nèi)存的黑科技?

今天,我們就來跳出 HashMap 的舒適區(qū),深度盤點(diǎn) Java 中那些同樣擁有 O ( 1 ) O(1) O(1) 查找性能,卻各具絕技的鍵值對存儲利器。

一、 先扒一扒 HashMap 真實的“時間復(fù)雜度”

在介紹其他利器之前,我們需要先戳破一個關(guān)于 HashMap 的常見幻覺:它的時間復(fù)雜度永遠(yuǎn)是 O ( 1 ) O(1) O(1) 嗎?

嚴(yán)格從算法理論來說,HashMap O ( 1 ) O(1) O(1) 只是平均時間復(fù)雜度。在底層,它基于“數(shù)組 + 鏈表/紅黑樹”實現(xiàn)。通過對 Key 計算哈希值并取模,它可以瞬間定位到數(shù)組的具體槽位(Bucket),這就是 O ( 1 ) O(1) O(1) 的核心支撐。

但在實際運(yùn)行中,它面臨著兩個無法逃避的“降速陷阱”:

  1. 哈希沖突(Hash Collision)的最壞情況
    當(dāng)大量的 Key 運(yùn)氣不佳,算出了相同的索引位置時,它們會被擠在同一個桶里。
    • 在 JDK 8 之前,這里會形成單鏈表,查找時間復(fù)雜度退化為 O ( n ) O(n) O(n)
    • 在 JDK 8 之后,引入了樹化機(jī)制(鏈表長度超 8 轉(zhuǎn)為紅黑樹),最壞時間復(fù)雜度被優(yōu)化為 O ( log ? n ) O(\log n) O(logn)。
  2. 擴(kuò)容(Resize)的隱藏代價
    當(dāng)元素個數(shù)達(dá)到閾值(容量 × \times × 加載因子 0.75)時,HashMap 會觸發(fā)擴(kuò)容。在這個瞬間,它需要開辟兩倍大小的新數(shù)組,并將老數(shù)據(jù)重新進(jìn)行 Hash 計算和搬移。這是一次極其昂貴的 O ( n ) O(n) O(n) 操作。

結(jié)論HashMap 是優(yōu)秀的常規(guī)武器,但它的 O ( 1 ) O(1) O(1) 是有代價的(基于概率的哈希計算與均攤分析)。

二、 并發(fā)之王:ConcurrentHashMap

適用場景:多線程高并發(fā)共享數(shù)據(jù)的 O ( 1 ) O(1) O(1) 讀寫。

在多線程環(huán)境下,普通的 HashMap 如果發(fā)生并發(fā)擴(kuò)容,可能會導(dǎo)致死循環(huán)(JDK 7)或數(shù)據(jù)丟失(JDK 8)。這時候必須請出 ConcurrentHashMap。

很多人誤以為保證線程安全一定會大幅拖慢速度,但 ConcurrentHashMap 的精妙之處就在于:它在保證極高并發(fā)安全性的同時,依然維持了平均 O ( 1 ) O(1) O(1) 的驚人性能。

  • JDK 8 的極致優(yōu)化:它拋棄了老版本臃腫的分段鎖(Segment),轉(zhuǎn)而直接使用 無鎖 CAS 算法 + synchronized 細(xì)粒度鎖。
  • 為什么快? 它把鎖的粒度縮小到了每一個哈希桶的頭節(jié)點(diǎn)。這意味著,只要兩個線程操作的 Key 哈希值不同(不在同一個桶里),它們就完全不會互相阻塞,真正做到了“只有沖突,才會排隊”。

三、 有序與高效兼得:LinkedHashMap

適用場景:需要按插入順序遍歷、或需要實現(xiàn) LRU 緩存。

哈希表最大的痛點(diǎn)是無序。遍歷一個 HashMap 輸出的順序,仿佛是隨機(jī)搖號的結(jié)果。如果你既想要 O ( 1 ) O(1) O(1) 的查找速度,又需要記錄放入數(shù)據(jù)的先后順序,LinkedHashMap 就是你的終極選擇。

核心原理:HashMap + 全局雙向鏈表。
它在普通 HashMap 的基礎(chǔ)上,為每一個節(jié)點(diǎn)額外增加了 beforeafter 兩個指針。所有的節(jié)點(diǎn)不僅存在于哈希桶里,還被一根無形的雙向鏈表串聯(lián)了起來。

它最強(qiáng)大的殺手锏是**“訪問順序(Access Order)”模式**:

// 第三個參數(shù) true 代表開啟“訪問順序”
LinkedHashMap<String, Integer> lruCache = new LinkedHashMap<>(16, 0.75f, true);

開啟后,任何被 getput 訪問過的節(jié)點(diǎn),都會瞬間被移動到雙向鏈表的末尾。而鏈表頭部自然就沉淀了“最久未被訪問的元素”。依靠這個特性,我們只需要寥寥幾行代碼,就能實現(xiàn)一個具有生產(chǎn)級別性能的 LRU 緩存。

四、 極致的性能巔峰:EnumMap

適用場景:當(dāng)你的 Key 是枚舉類型(Enum)時。

如果你面臨這樣一個場景:需要將特定的“狀態(tài)”、“類型”或“星期”映射到某個值,且 Key 都是預(yù)定義好的枚舉類。那么千萬別用 HashMapEnumMap 會給你展現(xiàn)什么叫真正的“降維打擊”。

public enum Day { MONDAY, TUESDAY, WEDNESDAY }
// 初始化 EnumMap,需傳入枚舉的 Class 對象
Map<Day, String> schedule = new EnumMap<>(Day.class);
schedule.put(Day.MONDAY, "開會");

為什么說它是巔峰?
因為它的底層根本沒有哈希表!既然枚舉類的實例個數(shù)在編譯期就是確定的,且每個枚舉自帶唯一的編號(ordinal()),EnumMap 在底層直接包裝了一個極其簡單的原生數(shù)組。

  • 沒有哈希計算:不需要調(diào)用 hashCode()。
  • 沒有哈希沖突:每個枚舉坑位固定,完全不需要鏈表或紅黑樹。
  • 沒有擴(kuò)容代價:數(shù)組大小固定等于枚舉實例的總數(shù)。

無論是最壞情況還是平均情況,它的時間復(fù)雜度都是嚴(yán)格且絕對的 O ( 1 ) O(1) O(1)。它是 Java 集合框架中運(yùn)行速度最快、內(nèi)存占用最少的 Map 實現(xiàn)。

五、 返璞歸真:原生數(shù)組(Array)

適用場景:Key 為連續(xù)或范圍可控的小整數(shù)。

最后,讓我們跳出面向?qū)ο蟮乃季S局限?;貧w數(shù)據(jù)結(jié)構(gòu)的本源,哈希表的終極目標(biāo)是什么?是直接尋址。

如果你的業(yè)務(wù)場景中,Key 是諸如用戶 ID(0~1000 之間)、HTTP 狀態(tài)碼(200500)、或者是每月的日期(131),你完全不需要引入任何 Map。

// Key 是狀態(tài)碼,Value 是錯誤描述
String[] errorMsgMap = new String[600]; 
errorMsgMap[404] = "Not Found";
errorMsgMap[500] = "Internal Error";
// 極速 O(1) 獲取
String msg = errorMsgMap[errorCode];

在這個場景下,Key 就是數(shù)組的下標(biāo)(Index),Value 就是數(shù)組的元素。
這是一種脫離了任何框架開銷,直接與 CPU 指令集和內(nèi)存總線對話的物理級 O ( 1 ) O(1) O(1)。沒有任何哈希結(jié)構(gòu)的性能可以超越原生數(shù)組。

總結(jié)建議:請收下這份“O(1) 選型指南”

在未來的開發(fā)中,當(dāng)你想寫下 new HashMap<>() 時,不妨停下來思考一秒鐘,看看以下對照表,是否還有更好的選擇:

存儲利器核心特點(diǎn)適用最佳場景
HashMap常規(guī)王者,基于概率的 O ( 1 ) O(1) O(1)絕大多數(shù)單線程、無需保證順序的常規(guī) K-V 存儲。
ConcurrentHashMap線程安全,無鎖優(yōu)化 O ( 1 ) O(1) O(1)必須應(yīng)對多線程高并發(fā)讀寫,且不接受阻塞性能下降。
LinkedHashMap記錄順序,鏈表尋址 O ( 1 ) O(1) O(1)需要按插入順序遍歷展示,或需要手寫實現(xiàn) LRU 緩存。
EnumMap絕對 O ( 1 ) O(1) O(1),沒有哈希沖突當(dāng) Key 的類型恰好是 enum 枚舉時(性能強(qiáng)推?。?。
原生數(shù)組硬件級尋址,降維打擊當(dāng) Key 是連續(xù)的、范圍較小的非負(fù)整數(shù)時。

“技術(shù)的魅力在于因地制宜。深刻理解每一把武器的內(nèi)部構(gòu)造和適用邊界”
ey 的類型恰好是 enum 枚舉時(性能強(qiáng)推?。?。 |
| 原生數(shù)組 | 硬件級尋址,降維打擊 | 當(dāng) Key 是連續(xù)的、范圍較小的非負(fù)整數(shù)時。 |

到此這篇關(guān)于不僅僅是 HashMap:盤點(diǎn) Java 中 O(1) 的鍵值對存儲利器的文章就介紹到這了,更多相關(guān)Java  O(1) 鍵值對存儲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java之函數(shù)式接口解讀

    java之函數(shù)式接口解讀

    這篇文章主要介紹了java之函數(shù)式接口,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 基于SpringBoot和Vue3的博客平臺的用戶注冊與登錄功能實現(xiàn)

    基于SpringBoot和Vue3的博客平臺的用戶注冊與登錄功能實現(xiàn)

    本教程將指導(dǎo)您如何使用Spring?Boot和Vue3實現(xiàn)用戶注冊與登錄功能。我們將使用Spring?Boot作為后端框架,Vue3作為前端框架,同時使用MySQL作為數(shù)據(jù)庫,感興趣的朋友可以參考一下
    2023-04-04
  • SpringBoot實現(xiàn)監(jiān)控Actuator,關(guān)閉redis監(jiān)測

    SpringBoot實現(xiàn)監(jiān)控Actuator,關(guān)閉redis監(jiān)測

    這篇文章主要介紹了SpringBoot實現(xiàn)監(jiān)控Actuator,關(guān)閉redis監(jiān)測,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • SpringBoot2.0整合tk.mybatis異常解決

    SpringBoot2.0整合tk.mybatis異常解決

    本文主要介紹了SpringBoot2.0整合tk.mybatis異常,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • SpringBoot使用AOP切面對請求進(jìn)行日志記錄方式

    SpringBoot使用AOP切面對請求進(jìn)行日志記錄方式

    這篇文章主要介紹了SpringBoot使用AOP切面對請求進(jìn)行日志記錄方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • SpringBoot項目實戰(zhàn)之?dāng)?shù)據(jù)交互篇

    SpringBoot項目實戰(zhàn)之?dāng)?shù)據(jù)交互篇

    這篇文章主要給大家介紹了關(guān)于SpringBoot項目實戰(zhàn)之?dāng)?shù)據(jù)交互篇的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-03-03
  • Java如何搭建一個個人網(wǎng)盤

    Java如何搭建一個個人網(wǎng)盤

    這篇文章主要介紹了Java如何搭建一個個人網(wǎng)盤,對網(wǎng)盤感興趣的讀者,可以參考一下
    2021-04-04
  • springboot相互依賴 server相互引用方式

    springboot相互依賴 server相互引用方式

    這篇文章主要介紹了springboot相互依賴 server相互引用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java 實戰(zhàn)項目基于遺傳算法學(xué)校排課系統(tǒng)的實現(xiàn)流程

    Java 實戰(zhàn)項目基于遺傳算法學(xué)校排課系統(tǒng)的實現(xiàn)流程

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+Springboot+Maven+mybatis+Vue+Mysql實現(xiàn)一個基于遺傳算法的學(xué)校排課系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • Spring Boot中l(wèi)ombok的安裝與使用詳解

    Spring Boot中l(wèi)ombok的安裝與使用詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot中l(wèi)ombok安裝與使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09

最新評論

八宿县| 阿克陶县| 双牌县| 全椒县| 克拉玛依市| 怀柔区| 祁门县| 务川| 六枝特区| 韶山市| 卢龙县| 阳江市| 托克逊县| 达孜县| 九江市| 乌拉特后旗| 福建省| 长汀县| 樟树市| 荔浦县| 铜川市| 普兰县| 尉犁县| 苏尼特左旗| 宿迁市| 太白县| 东山县| 深州市| 蒲江县| 澎湖县| 广饶县| 云南省| 夏邑县| 综艺| 邓州市| 宜良县| 宣威市| 宜都市| 南昌县| 盐城市| 南靖县|