Java Map完全指南:从基础到高级应用
文章目录
- 1. Map接口概述
- Map的基本特性
- 2. Map接口的核心方法
- 基本操作方法
- 批量操作方法
- 3. 主要实现类详解
- 3.1 HashMap
- 3.2 LinkedHashMap
- 3.3 TreeMap
- 3.4 ConcurrentHashMap
- 4. 高级特性和方法
- 4.1 JDK 1.8新增方法
- 4.2 Stream API结合使用
- 5. 性能比较和选择建议
- 性能对比表
- 选择建议
- 6. 最佳实践和注意事项
- 6.1 正确重写hashCode()和equals()
- 6.2 初始容量设置
- 6.3 避免并发修改异常
- 6.4 使用不可变Map
- 7. 实际应用场景
- 7.1 缓存实现
- 7.2 统计词频
- 7.3 分组操作
1. Map接口概述
Map是Java集合框架中的核心接口之一,用于存储键值对(key-value pairs)。与List和Set不同,Map不是Collection接口的子接口,而是一个独立的顶级接口。Map中的每个键都是唯一的,但值可以重复。
Map的基本特性
- 键(Key)必须唯一,值(Value)可以重复
- 一个键只能映射到一个值
- 不同键可以映射到相同的值
- 键和值都可以为null(取决于具体实现)
2. Map接口的核心方法
基本操作方法
// 添加键值对
V put(K key, V value)// 获取指定键的值
V get(Object key)// 移除指定键的键值对
V remove(Object key)// 检查是否包含指定键
boolean containsKey(Object key)// 检查是否包含指定值
boolean containsValue(Object value)// 获取Map大小
int size()// 检查Map是否为空
boolean isEmpty()// 清空Map
void clear()
批量操作方法
// 将另一个Map的所有键值对添加到当前Map
void putAll(Map<? extends K, ? extends V> m)// 获取所有键的集合
Set<K> keySet()// 获取所有值的集合
Collection<V> values()// 获取所有键值对的集合
Set<Map.Entry<K, V>> entrySet()
3. 主要实现类详解
3.1 HashMap
HashMap是Map接口最常用的实现类,基于哈希表实现。
特点:
- 允许null键和null值
- 非线程安全
- 无序存储
- 平均时间复杂度:O(1)
内部结构:
- JDK 1.8之前:数组 + 链表
- JDK 1.8及之后:数组 + 链表 + 红黑树
// HashMap示例
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("apple", 10);
hashMap.put("banana", 20);
hashMap.put("orange", 15);// 遍历HashMap
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());
}
3.2 LinkedHashMap
LinkedHashMap继承自HashMap,维护了插入顺序或访问顺序。
特点:
- 保持插入顺序或访问顺序
- 基于哈希表和双向链表实现
- 性能略低于HashMap
// LinkedHashMap示例
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("first", 1);
linkedHashMap.put("second", 2);
linkedHashMap.put("third", 3);// 输出顺序与插入顺序一致
linkedHashMap.forEach((k, v) -> System.out.println(k + ": " + v));
3.3 TreeMap
TreeMap基于红黑树实现,是有序的Map。
特点:
- 根据键的自然顺序或自定义Comparator排序
- 不允许null键,但允许null值
- 时间复杂度:O(log n)
// TreeMap示例
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("zebra", 26);
treeMap.put("apple", 1);
treeMap.put("banana", 2);// 按键的字典序输出
treeMap.forEach((k, v) -> System.out.println(k + ": " + v));
// 输出: apple: 1, banana: 2, zebra: 26
3.4 ConcurrentHashMap
ConcurrentHashMap是线程安全的HashMap实现。
特点:
- 线程安全
- 高并发性能
- 不允许null键和null值
- 使用分段锁机制(JDK 1.8改为CAS + synchronized)
// ConcurrentHashMap示例
Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("thread1", 1);
concurrentMap.put("thread2", 2);// 原子操作
concurrentMap.putIfAbsent("thread3", 3);
concurrentMap.computeIfAbsent("thread4", k -> 4);
4. 高级特性和方法
4.1 JDK 1.8新增方法
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);// getOrDefault - 获取值,如果不存在返回默认值
Integer value = map.getOrDefault("c", 0); // 返回0// putIfAbsent - 如果键不存在则添加
map.putIfAbsent("c", 3);// replace - 替换指定键的值
map.replace("a", 10);// compute - 计算新值
map.compute("a", (k, v) -> v * 2); // a的值变为20// merge - 合并值
map.merge("d", 1, (oldVal, newVal) -> oldVal + newVal);
4.2 Stream API结合使用
Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.put("banana", 20);
map.put("orange", 15);// 过滤并收集到新Map
Map<String, Integer> filtered = map.entrySet().stream().filter(entry -> entry.getValue() > 10).collect(Collectors.toMap(Map.Entry::getKey,Map.Entry::getValue));// 转换值
Map<String, String> transformed = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey,entry -> "Count: " + entry.getValue()));
5. 性能比较和选择建议
性能对比表
实现类 | 查找 | 插入 | 删除 | 有序性 | 线程安全 |
---|---|---|---|---|---|
HashMap | O(1) | O(1) | O(1) | 无 | 否 |
LinkedHashMap | O(1) | O(1) | O(1) | 插入顺序 | 否 |
TreeMap | O(log n) | O(log n) | O(log n) | 键排序 | 否 |
ConcurrentHashMap | O(1) | O(1) | O(1) | 无 | 是 |
选择建议
使用HashMap当:
- 需要最快的查找、插入、删除操作
- 不需要保持顺序
- 单线程环境
使用LinkedHashMap当:
- 需要保持插入顺序或访问顺序
- 需要实现LRU缓存
使用TreeMap当:
- 需要按键排序
- 需要范围查询功能
使用ConcurrentHashMap当:
- 多线程环境
- 需要高并发性能
6. 最佳实践和注意事项
6.1 正确重写hashCode()和equals()
public class Person {private String name;private int age;@Overridepublic boolean equals(Object obj) {if (this == obj) return true;if (obj == null || getClass() != obj.getClass()) return false;Person person = (Person) obj;return age == person.age && Objects.equals(name, person.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}
6.2 初始容量设置
// 如果已知Map的大小,设置初始容量可以提高性能
Map<String, Integer> map = new HashMap<>(16);// 对于已知大小的数据,计算合适的初始容量
int expectedSize = 100;
int initialCapacity = (int) (expectedSize / 0.75) + 1;
Map<String, Integer> optimizedMap = new HashMap<>(initialCapacity);
6.3 避免并发修改异常
Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);// 错误的做法 - 会抛出ConcurrentModificationException
// for (String key : map.keySet()) {
// if (key.equals("a")) {
// map.remove(key);
// }
// }// 正确的做法 - 使用Iterator
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {Map.Entry<String, Integer> entry = iterator.next();if (entry.getKey().equals("a")) {iterator.remove();}
}
6.4 使用不可变Map
// 创建不可变Map
Map<String, Integer> immutableMap = Map.of("apple", 10,"banana", 20,"orange", 15
);// 或者使用Collections.unmodifiableMap()
Map<String, Integer> originalMap = new HashMap<>();
originalMap.put("a", 1);
Map<String, Integer> unmodifiableMap = Collections.unmodifiableMap(originalMap);
7. 实际应用场景
7.1 缓存实现
public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int maxSize;public LRUCache(int maxSize) {super(16, 0.75f, true); // accessOrder = truethis.maxSize = maxSize;}@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return size() > maxSize;}
}
7.2 统计词频
public Map<String, Integer> countWords(String text) {Map<String, Integer> wordCount = new HashMap<>();String[] words = text.toLowerCase().split("\\s+");for (String word : words) {wordCount.merge(word, 1, Integer::sum);}return wordCount;
}
7.3 分组操作
// 将学生按年级分组
List<Student> students = getStudents();
Map<String, List<Student>> studentsByGrade = students.stream().collect(Collectors.groupingBy(Student::getGrade));
相关文章:
Java Map完全指南:从基础到高级应用
文章目录 1. Map接口概述Map的基本特性 2. Map接口的核心方法基本操作方法批量操作方法 3. 主要实现类详解3.1 HashMap3.2 LinkedHashMap3.3 TreeMap3.4 ConcurrentHashMap 4. 高级特性和方法4.1 JDK 1.8新增方法4.2 Stream API结合使用 5. 性能比较和选择建议性能对比表选择建…...

jvm 垃圾收集算法 详解
垃圾收集算法 分代收集理论 垃圾收集器的理论基础,它建立在两个分代假说之上: 弱分代假说:绝大多数对象都是朝生夕灭的。强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。 这两个分代假说共同奠定了多款常用的垃圾收集…...

[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制
Linux 内核作为一个多任务操作系统,其进程管理子系统是核心组成部分之一。无论是用户应用的运行、驱动行为的触发,还是系统调度决策,几乎所有操作都离不开进程的创建、调度与销毁。本文将从进程的概念出发,深入探讨 Linux 内核中进…...
Nginx Stream 层连接数限流实战ngx_stream_limit_conn_module
1.为什么需要连接数限流? 数据库/Redis/MQ 连接耗资源:恶意脚本或误配可能瞬间占满连接池,拖垮后端。防御慢速攻击:层叠式限速(连接数+带宽)可阻挡「Slow Loris」之类的 TCP 低速洪水。公平接入…...
Spring Boot 定时任务的使用
前言 在实际开发中,我们经常需要实现定时任务的功能,例如每天凌晨执行数据清理、定时发送邮件等。Spring Boot 提供了非常便捷的方式来实现定时任务,本文将详细介绍如何在 Spring Boot 中使用定时任务。 一、Spring Boot 定时任务简介 Spr…...

Flutter:下拉框选择
 文档地址dropdown_button2 // 限价、市价 状态final List<String> orderTypes [普通委托, 市价委托];String? selectedOrderType 普通委托;changeOrderType(String …...

SpringAI(GA):Nacos2下的分布式MCP
原文链接地址:SpringAI(GA):Nacos2下的分布式MCP 教程说明 说明:本教程将采用2025年5月20日正式的GA版,给出如下内容 核心功能模块的快速上手教程核心功能模块的源码级解读Spring ai alibaba增强的快速上手教程 源码级解读 版…...
AC68U刷梅林384/386版本后不能 降级回380,升降级解决办法
前些时间手贱更新了路由器的固件,384.18版本。结果发现了一堆问题,比如客户端列表加载不出来,软件中心打不开等等。想着再刷一下新的固件,结果死活刷不上去。最后翻阅了大量前辈的帖子找到了相关的处理办法。现在路由器中开启SSH&…...

[AI绘画]sd学习记录(二)文生图参数进阶
目录 7.高分辨率修复:以小博大8.细化器(Refiner):两模型接力9.随机数种子(Seed):复现图片吧 本文接续https://blog.csdn.net/qq_23220445/article/details/148460878?spm1001.2014.3001.5501…...

CRM管理系统中的客户分类与标签管理技巧:提升转化率的核心策略
在客户关系管理(CRM)领域,有效的客户分类与标签管理是提升销售效率、优化营销ROI的关键。据统计,使用CRM管理系统进行科学客户分层的企业,客户转化率平均提升35%(企销客数据)。本文将深入解析在CRM管理软件中实施客户分类与标签管理的最佳实践…...

怎么解决cesium加载模型太黑,程序崩溃,不显示,位置不对模型太大,Cesium加载gltf/glb模型后变暗
有时候咱们cesium加载模型时候型太黑,程序崩溃,不显示,位置不对模型太大怎么办 需要处理 可以联系Q:424081801 谢谢 需要处理 可以联系Q:424081801 谢谢...

【AI系列】BM25 与向量检索
博客目录 引言:信息检索技术的演进第一部分:BM25 算法详解第二部分:向量检索技术解析第三部分:BM25 与向量检索的对比分析第四部分:融合与创新:混合检索系统 引言:信息检索技术的演进 在信息爆…...
windows10搭建nfs服务器
windows10搭建nfs服务器 Windows10搭建NFS服务 - fuzidage - 博客园...
simulink这边重新第二次仿真时,直接UE5崩溃,然后simulink没有响应
提问 : simulink这边重新第二次仿真时,直接UE5崩溃,然后simulink没有响应 simulink和UE5仿真的时候,simulink这边先停止仿真(也就是官方要求的顺序——注意:如果先在UE5那边停止仿真,如果UE5这…...
react 常见的闭包陷阱深入解析
一、引子 先来看一段代码,你能说出这段代码的问题在哪吗? const [count, setCount] = useState(0); useEffect(() => {const timer = setTimeout(() => {setCount(count + 1);}, 1000);return () => clearTimeout(timer); }, []);正确答案: 这段代码存在闭包陷阱…...
【CATIA的二次开发22】关于抽象对象Document概念详细总结
在CATIA VBA开发中,Document对象是最核心、最基础的对象之一。它代表了当前在CATIA会话中打开的一个文档(文件)。 几乎所有与文件操作、模型访问相关的操作都始于获取一个Document对象。 一、Document对象概述 1、获取Document对象: 当前活动文档: 最常见的方式是获取用户…...

模拟法解题的思路与算法分享
我们先来看思路与算法: 使用变长数组对栈进行模拟。 如果操作是 ,那么访问数组的后两个得分,将两个得分之和加到总得分,并且将两个得分之和入栈。如果操作是 D,那么访问数组的最后一个得分,将得分乘以 2 …...

mysql密码正确SpringBoot和Datagrip却连接不上
报错信息:SQLException: Access denied for user ‘root‘‘localhost‘ (using password: YES) 原因可能是是有端口号冲突 我这里是禅道端口与MySQL冲突,禅道端口也是3306,ctrlaltdelete打开任务管理器,关闭mysqlzt …...

高保真组件库:数字输入框
拖入一个文本框。 拖入一个矩形,作为整个数字输入框的边框,边框颜色为灰色DCDEE2,圆角半径为4。 拖入一个向上的箭头图标作为增加按钮,再拖入一个矩形,将向上箭头图标放入矩形内。矩形:18x15,边框颜色DCDEE2,边框左下可见,箭头图标:8x5,矩形置底,组合在一起命名”增…...
人工智能赋能高中学科教学的应用与前景研究
一、引言 1.1 研究背景 在科技飞速发展的当下,人工智能(Artificial Intelligence,简称 AI)已成为全球瞩目的关键技术领域,深刻地改变着人们的生活、工作和学习方式。从智能家居设备到智能交通系统,从医疗…...

【Linux】awk 命令详解及使用示例:结构化文本数据处理工具
【Linux】awk 命令详解及使用示例:结构化文本数据处理工具 引言 awk 是一种强大的文本处理工具和编程语言,专为处理结构化文本数据而设计。它的名称来源于其三位创始人的姓氏首字母:Alfred Aho、Peter Weinberger 和 Brian Kernighan。 基…...

紫光同创FPGA系列实现Aurora 8b/10b协议
特性 1.兼容XILINX aurora IP核 2.支持X1、X2、X4、X8模式(根据硬件条件选择模式) 3.支持FRAMING和STREAMING 用户接口 4.自动初始化和维护链路状态 5.支持热插拔 6.支持扰码、解扰 7.支持流量控制 8.支持crc用户数据 9.支持全双工或者半双工模式 10.最…...

DAY 44 预训练模型
知识点回顾: 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战:resnet18 (一)预训练的概念 我们发现准确率最开始随着epoch的增加而增加。随着循环的更新,参数在不断发生更新。 所以…...
[Harmony]颜色初始化
默认初始化颜色 let color: Color 0xFF00FF 创建一个工具,用十六进制颜色和RGBA初始化颜色 // 颜色工具类 export class ColorUtils {/*** 十六进制颜色初始化(支持透明度)* param hex 支持格式:#RRGGBB、#AARRGGBB、0xRRGGBB、…...
指针与函数参数传递详解 —— 值传递与地址传递的区别及应用
资料合集下载链接: https://pan.quark.cn/s/472bbdfcd014 在C语言中,函数参数的传递方式主要有两种:值传递和地址传递(通过指针)。理解两者的区别及应用对于正确操作数据和优化程序逻辑至关重要。本文将通过…...

【NLP中向量化方式】序号化,亚编码,词袋法等
1.序号化 将单词按照词典排序,给定从0或者1或者2开始的序号即可,一般情况有几 个特征的单词: PAD表示填充字符,UNK表示未知字符 在这个例子中,我们可以看到我们分别将3个文本分为了4个token,每个token用左侧的词典表示…...

C++学习-入门到精通【16】自定义模板的介绍
C学习-入门到精通【16】自定义模板的介绍 目录) C学习-入门到精通【16】自定义模板的介绍前言一、类模板创建一个自定义类模板:Stack\<T\> 二、使用函数模板来操作类模板特化的对象三、非类型形参四、模板类型形参的默认实参五、重载函数模板 前言…...
关于脏读,幻读,可重复读的学习
mysql 可以查询当前事务隔离级别 默认是RR repeatable-read 如果要测脏读 要配成未提交读 RU 读到了未提交的数据。 3.演示不可重复读 要改成提交读 RC 这个是指事务还未结束,其他事务修改了值。导致我两次读的不一样。 4.RR–可以解决不可重复读 小总结&…...

源码级拆解:如何搭建高并发「数字药店+医保购药」一体化平台?
在全民“掌上看病、线上购药”已成常态的今天,数字药店平台正在以惊人的速度扩张。而将数字药店与医保系统打通,实现线上医保购药,更是未来互联网医疗的关键拼图。 那么,如何从技术底层搭建一个 支持高并发、可扩展、安全合规的数…...
旅行商问题(TSP)的 C++ 动态规划解法教学攻略
一、问题描述 旅行商问题(TSP)是一个经典的组合优化问题。给定一个无向图,图中的顶点表示城市,边表示两个城市之间的路径,边的权重表示路径的距离。一个售货员需要从驻地出发,经过所有城市后回到驻地&…...