Java中HashMap的使用操作
一、概念
HashMap 位于 java.util 包下。它實(shí)現(xiàn)了 Map 接口,提供了基于鍵值對(duì)(Key-Value)的數(shù)據(jù)存儲(chǔ)方式,并允許使用 null 作為鍵和值。
核心思想:使用“鍵(Key)”的哈希值來(lái)存儲(chǔ)和檢索“值(Value)”。
核心特點(diǎn):
- 基于哈希表:它使用哈希算法來(lái)存儲(chǔ)和檢索數(shù)據(jù),這使得在理想情況下,
get和put操作的時(shí)間復(fù)雜度可以達(dá)到 O(1)。 - 無(wú)序:
HashMap不保證其中元素的順序(即插入順序和訪問(wèn)順序),并且順序也可能會(huì)隨時(shí)間(如擴(kuò)容時(shí))而變化。如果需要有序,可以使用LinkedHashMap。 - 非線程安全:多個(gè)線程同時(shí)操作一個(gè)
HashMap可能會(huì)導(dǎo)致數(shù)據(jù)不一致。如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)HashMap并至少有一個(gè)線程修改了它,則必須在外部進(jìn)行同步?;蛘呤褂?nbsp;Collections.synchronizedMap()進(jìn)行包裝,或者更推薦使用ConcurrentHashMap。
二、常用操作
2.1 初始化
// 1. 最常見(jiàn)的無(wú)參構(gòu)造,默認(rèn)初始容量16,負(fù)載因子0.75 HashMap<String, Integer> map = new HashMap<>(); // 2. 指定初始容量(減少擴(kuò)容次數(shù),優(yōu)化性能) HashMap<String, Integer> mapWithCapacity = new HashMap<>(32); // 3. 指定初始容量和負(fù)載因子(高級(jí)用法,通常不需要) HashMap<String, Integer> mapWithFactor = new HashMap<>(32, 0.8f); // 4. 通過(guò)另一個(gè)Map來(lái)創(chuàng)建 HashMap<String, Integer> anotherMap = new HashMap<>(map);
擴(kuò)容機(jī)制:擴(kuò)充為原數(shù)組容量的2倍
當(dāng) HashMap 中的元素?cái)?shù)量(size)超過(guò)當(dāng)前閾值(threshold) 時(shí),就會(huì)觸發(fā)擴(kuò)容。
閾值 (threshold) = 容量 (capacity) * 負(fù)載因子 (load factor)
- 默認(rèn)示例:默認(rèn)容量為 16,默認(rèn)負(fù)載因子為 0.75。
- 那么閾值就是
16 * 0.75 = 12。 - 當(dāng)執(zhí)行
put()操作后,size變得大于 12(即 13)時(shí),就會(huì)觸發(fā)擴(kuò)容。
- 那么閾值就是
2.2 CRUD
HashMap<String, String> capitalCities = new HashMap<>();
// 添加與更新
// put(K key, V value) - 添加鍵值對(duì),如果key已存在,則更新其value
capitalCities.put("USA", "Washington D.C.");
capitalCities.put("Germany", "Berlin");
capitalCities.put("Germany", "Berlin"); // 重復(fù)放入,不會(huì)改變
capitalCities.put("Germany", "New Berlin"); // Key已存在,Value會(huì)被更新為 "New Berlin"
// putIfAbsent(K key, V value) - (Java 8+) 只有在key不存在或?qū)?yīng)的value為null時(shí),才放入
capitalCities.putIfAbsent("France", "Paris"); // 會(huì)放入,因?yàn)镕rance不存在
capitalCities.putIfAbsent("Germany", "Paris"); // 不會(huì)放入,因?yàn)镚ermany已存在,Value仍然是"New Berlin"
// 獲取元素
// get(Object key) - 根據(jù)key獲取value,如果key不存在,返回null
String capitalOfGermany = capitalCities.get("Germany"); // "New Berlin"
String capitalOfJapan = capitalCities.get("Japan"); // null
// getOrDefault(Object key, V defaultValue) - (Java 8+) key不存在時(shí)返回一個(gè)默認(rèn)值
String capitalOfJapanSafe = capitalCities.getOrDefault("Japan", "Not Found"); // "Not Found"
// 檢查元素是否存在
// containsKey(Object key) - 檢查某個(gè)key是否存在
boolean hasGermany = capitalCities.containsKey("Germany"); // true
boolean hasJapan = capitalCities.containsKey("Japan"); // false
// containsValue(Object value) - 檢查某個(gè)value是否存在(效率較低,需要遍歷)
boolean hasParis = capitalCities.containsValue("Paris"); // true
// 刪除元素
// remove(Object key) - 根據(jù)key刪除鍵值對(duì),返回被刪除的value
String removedValue = capitalCities.remove("Germany"); // removedValue = "New Berlin"
// remove(Object key, Object value) - (Java 8+) 只有當(dāng)key和value都匹配時(shí)才刪除
boolean isRemoved = capitalCities.remove("USA", "LA"); // false, 因?yàn)閂alue不匹配"Washington D.C.",刪除失敗
boolean isRemoved2 = capitalCities.remove("USA", "Washington D.C."); // true, 刪除成功2.3 遍歷
// 遍歷所有鍵:keySet()
for (String country : capitalCities.keySet()) {
System.out.println("Country: " + country);
// 可以通過(guò)key再get value,但效率較低(不推薦在循環(huán)內(nèi)這樣用)
// System.out.println("Capital: " + capitalCities.get(country));
}
// 遍歷所有值:values()
for (String capital : capitalCities.values()) {
System.out.println("Capital: " + capital);
}
// 遍歷所有鍵值對(duì):entrySet() (最推薦、最高效的方式)
for (Map.Entry<String, String> entry : capitalCities.entrySet()) {
String country = entry.getKey();
String capital = entry.getValue();
System.out.println(country + " -> " + capital);
}
// 使用 Java 8 forEach + Lambda 表達(dá)式 (最簡(jiǎn)潔)
capitalCities.forEach((country, capital) -> {
System.out.println(country + " -> " + capital);
});2.4 其他常用方法
// size() - 返回鍵值對(duì)的數(shù)量
int size = capitalCities.size();
// isEmpty() - 判斷是否為空
boolean isEmpty = capitalCities.isEmpty();
// clear() - 清空所有映射
capitalCities.clear();
// replace(K key, V oldValue, V newValue) - (Java 8+) 替換操作
capitalCities.replace("France", "Paris", "Lyon"); // 只有當(dāng)舊值匹配時(shí)才替換三、與其他Map的比較
| 特性 | HashMap | LinkedHashMap | TreeMap | Hashtable | ConcurrentHashMap |
|---|---|---|---|---|---|
| 排序保證 | 無(wú)順序 | 插入順序 或 訪問(wèn)順序 (LRU) | 鍵的自然順序 或 自定義比較器順序 | 無(wú)順序 | 無(wú)順序 |
是否允許 null | 允許 一個(gè) null key 和多個(gè) null value | 允許 一個(gè) null key 和多個(gè) null value | 不允許 null key (取決于Comparator) | 不允許 null key 或 null value | 不允許 null key 或 null value |
| 線程安全 | 否 (非同步) | 否 (非同步) | 否 (非同步) | 是 (同步,每個(gè)方法都用 synchronized 修飾) | 是 (采用分段鎖/CAS等更高效的并發(fā)控制) |
| 性能特點(diǎn) | O(1) 時(shí)間復(fù)雜度的 get/put (平均情況) | 比 HashMap 稍慢,因?yàn)橐S護(hù)鏈表 | O(log n) 時(shí)間復(fù)雜度的 get/put | 類(lèi)似 HashMap,但同步開(kāi)銷(xiāo)大,性能差 | 高并發(fā)性能極佳,讀操作通常無(wú)需鎖 |
| 底層實(shí)現(xiàn) | 數(shù)組 + 鏈表/紅黑樹(shù) (哈希表) | HashMap + 雙向鏈表 (維護(hù)順序) | 紅黑樹(shù) | 數(shù)組 + 鏈表 (哈希表) | 數(shù)組 + 鏈表/紅黑樹(shù) + CAS + 分段鎖 (JDK 7/8 不同) |
| 迭代順序一致性 | 不保證,甚至可能隨時(shí)間變化 | 保證,與插入順序或訪問(wèn)順序一致 | 保證,根據(jù)鍵的順序排序 | 不保證 | 不保證 |
| 引入版本 | JDK 1.2 | JDK 1.4 | JDK 1.2 | JDK 1.0 (是古老遺留類(lèi)) | JDK 1.5 (java.util.concurrent 包) |
到此這篇關(guān)于Java中HashMap的使用操作的文章就介紹到這了,更多相關(guān)Java HashMap內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于 Cursor 開(kāi)發(fā) Spring Boot 項(xiàng)目詳細(xì)攻略
Cursor是集成GPT4、Claude3.5等LLM的VSCode類(lèi)AI編程工具,支持SpringBoot項(xiàng)目開(kāi)發(fā)全流程,涵蓋環(huán)境配置、代碼生成、數(shù)據(jù)庫(kù)連接及部署,提供智能輔助、代碼優(yōu)化與錯(cuò)誤修復(fù)功能,助力高效開(kāi)發(fā),本文給大家介紹基于Cursor開(kāi)發(fā)Spring Boot項(xiàng)目詳細(xì)攻略,感興趣的朋友一起看看吧2025-09-09
Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實(shí)現(xiàn)
這篇文章主要介紹了Java基礎(chǔ)之面向?qū)ο髾C(jī)制(多態(tài)、繼承)底層實(shí)現(xiàn),文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
Java將不同的List集合復(fù)制到另一個(gè)集合常見(jiàn)的方法
在Java中,有時(shí)候我們需要將一個(gè)List對(duì)象的屬性值復(fù)制到另一個(gè)List對(duì)象中,使得兩個(gè)對(duì)象的屬性值相同,這篇文章主要介紹了Java將不同的List集合復(fù)制到另一個(gè)集合常見(jiàn)的方法,需要的朋友可以參考下2024-09-09
Java設(shè)計(jì)模式之創(chuàng)建者模式詳解
這篇文章主要介紹了Java設(shè)計(jì)模式之創(chuàng)建者模式詳解,創(chuàng)建者模式,顧名思義,就是提供友好的創(chuàng)建對(duì)象的方式?,對(duì)象都是?new?出來(lái)的,但是在一些情況下,這種方式不是很友好,首先,它不夠直觀,需要的朋友可以參考下2023-08-08
Java實(shí)現(xiàn)按年月打印日歷功能【基于Calendar】
這篇文章主要介紹了Java實(shí)現(xiàn)按年月打印日歷功能,涉及java基于Calendar進(jìn)行日期運(yùn)算的相關(guān)操作技巧,需要的朋友可以參考下2018-03-03
SpringBoot?+?Vue?+?ElementUI?實(shí)現(xiàn)?el-table?分頁(yè)功能(詳細(xì)步驟)
本文詳細(xì)介紹了使用SpringBoot和Vue.js結(jié)合ElementUI實(shí)現(xiàn)分頁(yè)功能的數(shù)據(jù)表格,從后端分頁(yè)邏輯到前端展示和狀態(tài)管理,全面解析如何高效處理大量數(shù)據(jù),提升用戶(hù)體驗(yàn)與系統(tǒng)性能,感興趣的朋友跟隨小編一起看看吧2024-09-09
springboot項(xiàng)目中全局設(shè)置用UTC+8
本文主要介紹了springboot項(xiàng)目中全局設(shè)置用UTC+8,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04

