Map接口-實現類HashMap

目錄

一、什么是Map?

二、實現類HashMap

1.關鍵特點

無序、key唯一、value允許重復、key和value允許為null。

2.數據結構

2.1 JDK 1.7

2.2 JDK 1.8

2.3 關鍵參數

2.4 關鍵計算

3.擴容方式

3.1 初始化

3.2 擴容

4.常見方法

4.1 根據key存入value

4.2 根據key獲取value

4.3 判斷Map

4.4 根據key替換value

4.5 根據key刪除value

4.6 遍歷Map

5.HashMap(put)底層原理


一、什么是Map?

(1)Map是一種鍵值對集合,每一個元素都包含一個 鍵對象(key) 和一個 值對象(value)。

(2)Map集合中,鍵不允許重復,值可以重復。 (比如身份證與姓名)

(3)鍵和值是一一對應的,通過鍵可以找到與之對應的唯一的值。

(4)key和value必須是引用數據類型。

二、實現類HashMap

1.關鍵特點

無序、key唯一、value允許重復、key和value允許為null。

2.數據結構

2.1 JDK 1.7

數組+單向鏈表

在鏈表中插入元素,采用【頭插法】

2.2 JDK 1.8

數組+單向鏈表+紅黑樹

在鏈表中插入元素時,采用【尾插法】

2.3 關鍵參數

(1)Node<K, V>[ ] table:

????????????????保存KV鍵值對的數組,每個KV鍵值對都被封裝成一個Node對象。

????????????????數組容量決定了HashMap對內存的占用大小。

(2)float loadFactor:

????????????????加載因子(填充因子)。

????????????????加載因子默認為0.75,代表HashMap對數組容量的使用率為75%,超過該使用率,則數組需要進行擴容。

????????????????加載因子決定了HashMap對數組的使用率,加載因子越高,則表示允許填滿的元素就越多,集合的空間利用率就越高,但是沖突的機會增加。反之,越小則沖突的機會就會越少,但是空間很多就浪費。

(3)int threshold:

????????????????擴容閾值。

????????????????用于判斷數組是否需要進行擴容。

????????????????擴容閾值threshold = 數組容量 × 加載因子。

(4)size : int?

????????????????KV鍵值對的數量。

2.4 關鍵計算

(1)hash()函數:

(h = key.hashCode()) ^ (h >>> 16):在key原有哈希值的基礎上,與哈希值的高16位進行異或運算,計算出的哈希值更佳散列,不易出現哈希沖突。

(2)下標計算:JDK 1.7 :hash % 數組長度。

? ? ? ? ? ? ? ? ? ? ? ? ? ? JDK 1.8:(數組長度 - 1) & hash。提高性能--數組長度必須為2的N次冪。

3.擴容方式

3.1 初始化

(1)public HashMap():加載因子默認為為0.75。

(2)public HashMap(int initialCapacity, float loadFactor):指定容量和加載因子。

3.2 擴容

(1)添加第一個KV鍵值對,數組如果為空,則默認擴容為16。

(2)加入元素時,如果鏈表長度大于閾值(默認為 8)并且數組長度小于64,會產生數組擴容;*2。

(3)添加元素后,當HashMap中的元素個數超過【數組大小 × 加載因子(LoadFactor)】時,原數組擴容2倍。例如:加載因子(LoadFactor)的默認值為0.75,數組容量默認為16,當HashMap中元素個數超過16 × 0.75=12的時候,數組的容量擴容為16×2 =32;

4.常見方法

4.1 根據key存入value

(1)V put(K key, V value):存入【KV鍵值對】,如果key存在,則覆蓋【原value值】,保存后,返回【原value值】。

(2)void putAll(Map m):將【指定map】中的所有KV鍵值對,存入【當前map】。

(3)V putIfAbsent(K key, V value):如果key不存在,則保存value,并返回【null】;如果key已經存在,則不保存value,并返回【原value值】。

4.2 根據key獲取value

(1)V get(Object key):根據key,返回【value值】;如果key不存在,則返回【null】。

(2)V getOrDefault(Object key, V defaultValue):根據key,返回【value值】;如果key不存在,則返回【默認值】。

4.3 判斷Map

(1)boolean containsKey(Object key):判斷key是否存在。

(2)boolean containsValue(Object value):判斷value是否存在。

(3)boolean isEmpty():判斷map中的【KV鍵值對】數量是否為0。

(4)int size():獲取map中的【KV鍵值對】數量。

4.4 根據key替換value

(1)V replace(K key, V value):根據key,替換value,并返回【原value值】;如果key不存在,則返回【null】。

(2)boolean replace(K key, V oldValue, V newValue):根據key和value,替換value,修改成功,返回【true】;如果key和value不存在,則替換失敗,返回【false】。

4.5 根據key刪除value

(1)V remove(Object key):根據key,刪除【KV鍵值對】,并返回【原value值】。

(2)boolean remove(Object key, Object value):根據key和value,刪除【KV鍵值對】,則刪除成功,返回【true】;如果key和value不存在,則刪除失敗,返回【false】。

(3)clear():清除map中的鍵值對。

4.6 遍歷Map

(1)Set<K> keySet():獲取所有key。

(2)Collection<V> values():獲取所有value。

(3)Set<Map.Entry<K,V>> entrySet():獲取所有【KV鍵值對】,每個【KV鍵值對】使用【Entry類型的對象】封裝。

public class Demo01 {public static void main(String[] args) {//HashMap 無序,且key是唯一的,value是可重復的HashMap<String,String> hashMap=new HashMap<>();hashMap.put("110","北京");hashMap.put("120","天津");hashMap.put("130","河北");hashMap.put("610","陜西");hashMap.put("610","甘肅");hashMap.put("620","甘肅");System.out.println(hashMap);}
}
public class Demo02 {public static void main(String[] args) {HashMap<String, String> hashMap = new HashMap<>();insertElement(hashMap);//selectElement(hashMap);deleteElement(hashMap);}public static void insertElement(HashMap<String, String> hashMap) {System.out.println("========進入到添加方法中========");//1.V put(K key, V value)存鍵值對,如果集合不存在此鍵,直接存,返回值為null//當存在此鍵時,返回值為上一次的鍵對應的value,用此value覆蓋String item1 = hashMap.put("110", "北京");String item2 = hashMap.put("110", "天津");hashMap.put("130", "河北");hashMap.put("610", "陜西");System.out.println("第一次存返回值:" + item1);System.out.println("第二次存返回值:" + item2);//void putAll(Map m)HashMap<String, String> hashMap1 = new HashMap<>();hashMap1.put("620", "甘肅");hashMap1.put("630", "寧夏");hashMap1.put("610", "內蒙");//將指定map中的所有KV鍵值對,存入到當前map;hashMap.putAll(hashMap1);System.out.println(hashMap);//V  putIfAbsent(K key,V value)如果存在此鍵,返回值為鍵對應的舊值,如果不存在則存返回nullString oldValue = hashMap.putIfAbsent("611", "西安");System.out.println("putIfAbsent再次存610的鍵:" + oldValue);System.out.println(hashMap);}public static void selectElement(HashMap<String, String> hashMap) {System.out.println("=======進入到查看方法中=======");System.out.println("目前map中的元素為:" + hashMap);//V get(Object key)根據key,返回value值,如果key不存在,則返回nullString value1 = hashMap.get("120");System.out.println("鍵120對應的值為" + value1);//V getOrDefault(Object key,V defaultValue)//根據key,返回value值,如果key不存咋,則返回默認值String value2 = hashMap.getOrDefault("120", "不知道");System.out.println("鍵120對應的值為:" + value2);//boolean containsKey(Object key)判斷key是否存在boolean b1 = hashMap.containsKey("611");System.out.println("鍵611是否存在:" + b1);//boolean containsValue(Object value)判斷value是否存在boolean b2 = hashMap.containsValue("寧夏");System.out.println("值寧夏是否存在:" + b2);//boolean isEmpty()判斷map中的【KV鍵值對】數量是否為0System.out.println("集合map是否為空:" + hashMap.isEmpty());//int size()獲取map中的【KV鍵值對】數量System.out.println("集合的size:" + hashMap.size());}public static void deleteElement(HashMap<String, String> hashMap){System.out.println("========進入到刪除和修改方法中========");System.out.println("目前map中的元素為:" + hashMap);//V replace(K key, V value)根據key,替換value,并返回【原value值】;如果key不存在,則返回【null】String value=hashMap.replace("110","北京");System.out.println(value);System.out.println("修改后的hashmap:"+hashMap);//boolean replace(K key, V oldValue, V newValue)//根據key和value,替換value,修改成功,返回【true】;如果key和value不存在,則替換失敗,返回【false】;boolean b1=hashMap.replace("610","內蒙","陜西");System.out.println(b1);System.out.println("修改后的hashmap:"+hashMap);//V remove(Object key)根據key,刪除【KV鍵值對】,并返回【原value值】String str=hashMap.remove("130");System.out.println(str);System.out.println("刪除后的hashmap:"+hashMap);//boolean remove(Object key, Object value)//根據key和value,刪除【KV鍵值對】,則刪除成功,返回【true】;如果key和value不存在,則刪除失敗,返回【false】;boolean b2=hashMap.remove("630","陜西");System.out.println(b2);System.out.println("刪除后的hashmap:"+hashMap);//clear()hashMap.clear();System.out.println("清空后:"+hashMap);}
}
public class Demo03 {public static void main(String[] args) {HashMap<String,String> hashMap=new HashMap<>();hashMap.put("110","北京");hashMap.put("120","天津");hashMap.put("130","河北");hashMap.put("610","陜西");hashMap.put("620","甘肅");System.out.println(hashMap);//1.Set<K> keySet()獲取所有的鍵Set<String> keys = hashMap.keySet();for (String key : keys) {String value = hashMap.get(key);System.out.printf("鍵為:%s - 值為%s\n", key, value);}//2.獲取所有的value Collection<V> values()Collection<String> values = hashMap.values();System.out.println(values);//3.獲取所有的鍵值對集合對象Set<Map.Entry<String, String>> entries = hashMap.entrySet();for (Map.Entry<String, String> entry : entries) {System.out.println(entry.getKey() + "==" + entry.getValue());}}
}

5.HashMap(put)底層原理

/*** 數據結構: Node<K,V>[] table, 數組 + 鏈表 + 紅黑樹* put整理:* 1.通過i = (n - 1) & hash計算當前鍵值對要存放的下標位置, 此處元素是否為null,如果為null直接存儲* 2.如果不為null,判斷當前的下標元素key是否和要存儲的key完全一樣, key一樣, 則value進行覆蓋* 3.鍵如果不同, 則產生了hash沖突, 將當前要存放的鍵值對存放進來*    3.1判斷當前的節點是否是樹形節點, 如果是樹形節點, 以樹形存放方式操作*    3.2如果不是樹形節點, 就是鏈表: 找p.next == null的位置(找的過程中也會和鏈表的每個元素的key進行相等比較),*        去進行p.next的賦值操作*        鏈表元素個數的判斷>8 && 數組長度 <64  -- 擴容, 2倍擴容*        鏈表元素個數的判斷>8 && 數組長度 >64  會將鏈表轉換為紅黑樹**        存放完元素如果達到擴容閾值(容量 × 加載因子,默認 0.75), 2倍擴容。* 擴容:* 無參構造初始化對象, 第一次添加元素時, 首次擴容到16

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93045.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93045.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93045.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

深入解析Hadoop如何實現數據可靠性:三副本策略、校驗和驗證與Pipeline復制

Hadoop數據可靠性的重要性在大數據時代&#xff0c;數據可靠性已成為企業數字化轉型的生命線。根據IDC預測&#xff0c;到2025年全球數據總量將增長至175ZB&#xff0c;其中企業數據占比超過60%。面對如此龐大的數據規模&#xff0c;任何數據丟失或損壞都可能造成數百萬美元的經…

15.6 DeepSpeed+Transformers實戰:LLaMA-7B訓練效率提升210%,顯存直降73%

DeepSpeedTransformers實戰:LLaMA-7B訓練效率提升210%的底層邏輯與實操指南 當LLaMA-7B的訓練顯存需求達到78GB時,單卡A100(80GB)幾乎瀕臨溢出,更不用說普通GPU集群。而DeepSpeed與Hugging Face Transformers的深度集成,通過"ZeRO三階段優化+混合精度+梯度檢查點&q…

Nginx + PM2 實現Express API + React 前端 本地測試服務器搭建

一、工具準備 openSSL&#xff1a;需要針對https請求頭 生成對應的 自簽名證書。 Nginx&#xff1a;服務器搭建工具 nodeJS: Express API運行環境 PM2: node進程管理器。用于替代npm命令管理 啟動命令。 二、openSSL 本地自簽名證書生成。 創建服務器空文件夾&#xff08…

OTG原理講解

文章目錄一、什么是 OTG&#xff08;USB On-The-Go&#xff09;&#xff1f;? OTG 的定義&#xff1a;二、傳統 USB 與 OTG 的區別三、OTG 的核心機制&#xff1a;**通過 ID 引腳判斷角色**1. 對于 Micro-USB OTG&#xff1a;2. 電路如何感知 ID 引腳&#xff1f;四、OTG 電路…

數據結構系列之紅黑樹

前言 紅黑樹是比較重要的一顆樹了&#xff0c;map和set的底層就是紅黑樹&#xff0c;一定要牢牢記住。 一、什么是紅黑樹 首先&#xff1a;紅黑樹仍然是一顆搜索二叉樹&#xff0c;但他引入了顏色這一概念&#xff0c;每個結點多一個存儲位來存儲顏色&#xff0c;它通過維護下…

在OpenMP中,#pragma omp的使用

在OpenMP中&#xff0c;#pragma omp for 和 #pragma omp parallel for&#xff08;或 #pragma omp parallel num_threads(N)&#xff09;有本質區別&#xff0c;主要體現在 并行區域的創建 和 工作分配方式 上。以下是詳細對比&#xff1a;1. #pragma omp for 作用 僅分配循環迭…

停止“玩具式”試探:深入拆解ChatGPT Agent的技術棧與實戰避坑指南

摘要&#xff1a; 當許多人還在用ChatGPT寫周報、生成樣板代碼時&#xff0c;其底層的Agent化能力已經預示著一場深刻的開發范式變革。這不再是簡單的“AI輔助”&#xff0c;而是“人機協同”的雛形。本文旨在穿透表面的功能宣傳&#xff0c;從技術棧層面拆解Agent模式的實現基…

element-plus安裝以及使用

element-plus時為vue.js 3開發的組件庫。 在引入前需要做如下準備 安裝node.js https://blog.csdn.net/zlpzlpzyd/article/details/147704723 安裝vue的腳手架vue-cli https://blog.csdn.net/zlpzlpzyd/article/details/149647351 安裝element-plus github地址 https://git…

學習隨想錄-- web3學習入門計劃

#60 轉方向 web3 golang 以太坊應用 這是課表部分&#xff08;Golang以太坊方向&#xff09; Sheet b站up學習計劃 第一階段&#xff1a;基礎能力構建&#xff08;1-2 個月&#xff09; 學習目標 掌握 Golang 核心語法與以太坊底層基礎概念&#xff0c;建立開發知識框架。…

【RAG優化】PDF復雜表格解析問題分析

在構建檢索增強生成(RAG)應用時,PDF文檔無疑是最重要、也最普遍的知識來源之一。然而,PDF中潛藏著RAG系統的難點問題——復雜表格。這些表格富含高密度的結構化信息,對回答精準問題至關重要,但其復雜的視覺布局(多層表頭、合并單元格、跨頁表格等)常常讓標準的文本提取…

ReAct Agent(LangGraph實現)

文章目錄參考資料一 AI Agent二 ReAct三 LangGraph實現ReAct代理3.1 SerperAPI實時聯網搜索3.2 ReAct實現參考資料 entic RAG 架構的基本原理與應用入門 一 AI Agent AI Agent 整個過程是一個動態循環。Agent不斷從環境中學習&#xff0c;通過其行動影響環境&#xff0c;然后…

如何從0到1的建立組織級項目管理體系【現狀診斷】

今天我想給大家分享是“如何在企業中從0到1的去建立PMO的組織級項目管理體系。”的系列文章&#xff0c;這是我近幾年來一直在努力的嘗試去探索和實踐的過程&#xff0c;從0到1的過程。當我最開始去接手這樣一個場景的時候所需要做的第一件事情是診斷和差距分析。這是多年以來做…

網絡通信協議詳解:TCP協議 vs HTTP協議

在計算機網絡中&#xff0c;TCP&#xff08;傳輸控制協議&#xff09;和HTTP&#xff08;超文本傳輸協議&#xff09;是兩個核心協議&#xff0c;但它們的職責和層級完全不同。TCP是底層傳輸協議&#xff0c;負責數據的可靠傳輸&#xff1b;HTTP是應用層協議&#xff0c;定義了…

[Qt]QString隱式拷貝

引言在Qt框架中&#xff0c;QString 作為字符串處理的核心類&#xff0c;其高效的內存管理機制一直是開發者津津樂道的特性。這背后的關鍵便是 隱式共享&#xff08;Implicit Sharing&#xff09;&#xff0c;也稱為 寫時復制&#xff08;Copy-On-Write, COW&#xff09;。本文…

命令行創建 UV 環境及本地化實戰演示—— 基于《Python 多版本與開發環境治理架構設計》的最佳實踐

命令行創建 UV 環境及本地化實戰&#xff1a;基于架構設計的最佳實踐 Python 多版本環境治理理念驅動的系統架構設計&#xff1a;三維治理、四級隔離、五項自治 原則-CSDN博客 使用 Conda 工具鏈創建 UV 本地虛擬環境全記錄——基于《Python 多版本與開發環境治理架構設計》-CS…

跨域問題全解:從原理到實戰

在計算機網絡中&#xff0c;跨域&#xff08;Cross-Origin&#xff09; 指的是瀏覽器出于安全考慮&#xff0c;限制網頁腳本&#xff08;如 JavaScript&#xff09;向與當前頁面不同源&#xff08;Origin&#xff09; 的服務器發起請求的行為。這是由瀏覽器的同源策略&#xff…

(46)elasticsearch-華為云CCE無狀態負載部署

一、準備好elasticsearch鏡像并提前上傳到鏡像倉庫 此次準備的是elasticsearch:v7.10.2 二、開始部署 負載名稱:es-deployment 注意:內部配額太低會造成多次重啟 環境變量: #單節點啟動(實例pod可以多增加幾個) discovery.type single-node 三、添加svc 四、注意:…

HCLP--MGER綜合實驗

一、拓撲圖二、需求1、R5為ISP&#xff0c;只能進行IP地址配置&#xff0c;其所有地址均配為公有I地址; 2、R1和R5間使用PPP的PAP認證&#xff0c;R5為主認證方&#xff0c; R2與R5之間使用ppp的CHAP認證&#xff0c;R5為主認證方; R3與R5之間使用HDLc封裝; 3、R1、R2、R3構建一…

idea中無法刪除模塊,只能remove?

1.先對module右鍵想要刪除的module&#xff0c;選擇remove module&#xff08;這是idea為了避免誤操作&#xff09; 2.在remove module后&#xff0c;模塊并未從項目結構中刪除&#xff08;磁盤中也依舊存在&#xff09;&#xff0c;但再次右擊你會發現&#xff0c;出現了del…

青藤天睿RASP再次發威!捕獲E簽寶RCE 0day漏洞

在2025年HVV關鍵攻防節點上&#xff0c;攻擊隊對E簽寶電子合同服務發起的0day攻擊被青藤天睿RASP截獲。該漏洞可使攻擊者在未授權情況下實現服務器遠程代碼執行&#xff08;RCE&#xff09;&#xff0c;進而控制服務器&#xff0c;構成橫向滲透的關鍵跳板。>>>>漏洞…