Java Map完全指南:从基础到高级应用

news2025/6/8 23:14:30

文章目录

    • 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. 性能比较和选择建议

性能对比表

实现类查找插入删除有序性线程安全
HashMapO(1)O(1)O(1)
LinkedHashMapO(1)O(1)O(1)插入顺序
TreeMapO(log n)O(log n)O(log n)键排序
ConcurrentHashMapO(1)O(1)O(1)

选择建议

使用HashMap当:

  • 需要最快的查找、插入、删除操作
  • 不需要保持顺序
  • 单线程环境

使用LinkedHashMap当:

  • 需要保持插入顺序或访问顺序
  • 需要实现LRU缓存

使用TreeMap当:

  • 需要按键排序
  • 需要范围查询功能

使用ConcurrentHashMap当:

  • 多线程环境
  • 需要高并发性能

6. 最佳实践和注意事项

6.1 正确重写hashCode()和equals()

public class Person {
    private String name;
    private int age;
    
    @Override
    public 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);
    }
    
    @Override
    public 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 = true
        this.maxSize = maxSize;
    }
    
    @Override
    protected 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));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2404684.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jvm 垃圾收集算法 详解

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

[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制

Linux 内核作为一个多任务操作系统&#xff0c;其进程管理子系统是核心组成部分之一。无论是用户应用的运行、驱动行为的触发&#xff0c;还是系统调度决策&#xff0c;几乎所有操作都离不开进程的创建、调度与销毁。本文将从进程的概念出发&#xff0c;深入探讨 Linux 内核中进…

Flutter:下拉框选择

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/d4 b70dec92594838a8b2c130717938aa.png) 文档地址dropdown_button2 // 限价、市价 状态final List<String> orderTypes [普通委托, 市价委托];String? selectedOrderType 普通委托;changeOrderType(String …

SpringAI(GA):Nacos2下的分布式MCP

原文链接地址&#xff1a;SpringAI(GA)&#xff1a;Nacos2下的分布式MCP 教程说明 说明&#xff1a;本教程将采用2025年5月20日正式的GA版&#xff0c;给出如下内容 核心功能模块的快速上手教程核心功能模块的源码级解读Spring ai alibaba增强的快速上手教程 源码级解读 版…

[AI绘画]sd学习记录(二)文生图参数进阶

目录 7.高分辨率修复&#xff1a;以小博大8.细化器&#xff08;Refiner&#xff09;&#xff1a;两模型接力9.随机数种子&#xff08;Seed&#xff09;&#xff1a;复现图片吧 本文接续https://blog.csdn.net/qq_23220445/article/details/148460878?spm1001.2014.3001.5501…

CRM管理系统中的客户分类与标签管理技巧:提升转化率的核心策略

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

怎么解决cesium加载模型太黑,程序崩溃,不显示,位置不对模型太大,Cesium加载gltf/glb模型后变暗

有时候咱们cesium加载模型时候型太黑&#xff0c;程序崩溃&#xff0c;不显示&#xff0c;位置不对模型太大怎么办 需要处理 可以联系Q:424081801 谢谢 需要处理 可以联系Q:424081801 谢谢

【AI系列】BM25 与向量检索

博客目录 引言&#xff1a;信息检索技术的演进第一部分&#xff1a;BM25 算法详解第二部分&#xff1a;向量检索技术解析第三部分&#xff1a;BM25 与向量检索的对比分析第四部分&#xff1a;融合与创新&#xff1a;混合检索系统 引言&#xff1a;信息检索技术的演进 在信息爆…

模拟法解题的思路与算法分享

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

mysql密码正确SpringBoot和Datagrip却连接不上

报错信息&#xff1a;SQLException: Access denied for user ‘root‘‘localhost‘ (using password: YES&#xff09; 原因可能是是有端口号冲突 我这里是禅道端口与MySQL冲突&#xff0c;禅道端口也是3306&#xff0c;ctrlaltdelete打开任务管理器&#xff0c;关闭mysqlzt …

高保真组件库:数字输入框

拖入一个文本框。 拖入一个矩形,作为整个数字输入框的边框,边框颜色为灰色DCDEE2,圆角半径为4。 拖入一个向上的箭头图标作为增加按钮,再拖入一个矩形,将向上箭头图标放入矩形内。矩形:18x15,边框颜色DCDEE2,边框左下可见,箭头图标:8x5,矩形置底,组合在一起命名”增…

【Linux】awk 命令详解及使用示例:结构化文本数据处理工具

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

紫光同创FPGA系列实现Aurora 8b/10b协议

特性 1.兼容XILINX aurora IP核 2.支持X1、X2、X4、X8模式&#xff08;根据硬件条件选择模式&#xff09; 3.支持FRAMING和STREAMING 用户接口 4.自动初始化和维护链路状态 5.支持热插拔 6.支持扰码、解扰 7.支持流量控制 8.支持crc用户数据 9.支持全双工或者半双工模式 10.最…

DAY 44 预训练模型

知识点回顾&#xff1a; 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战&#xff1a;resnet18 &#xff08;一&#xff09;预训练的概念 我们发现准确率最开始随着epoch的增加而增加。随着循环的更新&#xff0c;参数在不断发生更新。 所以…

【NLP中向量化方式】序号化,亚编码,词袋法等

1.序号化 将单词按照词典排序&#xff0c;给定从0或者1或者2开始的序号即可&#xff0c;一般情况有几 个特征的单词: PAD表示填充字符&#xff0c;UNK表示未知字符 在这个例子中&#xff0c;我们可以看到我们分别将3个文本分为了4个token&#xff0c;每个token用左侧的词典表示…

C++学习-入门到精通【16】自定义模板的介绍

C学习-入门到精通【16】自定义模板的介绍 目录&#xff09; C学习-入门到精通【16】自定义模板的介绍前言一、类模板创建一个自定义类模板&#xff1a;Stack\<T\> 二、使用函数模板来操作类模板特化的对象三、非类型形参四、模板类型形参的默认实参五、重载函数模板 前言…

源码级拆解:如何搭建高并发「数字药店+医保购药」一体化平台?

在全民“掌上看病、线上购药”已成常态的今天&#xff0c;数字药店平台正在以惊人的速度扩张。而将数字药店与医保系统打通&#xff0c;实现线上医保购药&#xff0c;更是未来互联网医疗的关键拼图。 那么&#xff0c;如何从技术底层搭建一个 支持高并发、可扩展、安全合规的数…

Hadoop 3.x 伪分布式 8088端口无法访问问题处理

【Hadoop】YARN ResourceManager 启动后 8088 端口无法访问问题排查与解决(伪分布式启动Hadoop) 在配置和启动 Hadoop YARN 模块时&#xff0c;发现虽然 ResourceManager 正常启动&#xff0c;JPS 进程中也显示无误&#xff0c;但通过浏览器访问 http://主机IP:8088 时却无法打…

零基础在实践中学习网络安全-皮卡丘靶场(第十期-Over Permission 模块)

经过这么长时间的学习&#xff0c;我相信大家已经有了很大的信心&#xff0c;有可能会有看不起的意思&#xff0c;因为皮卡丘是基础靶场&#xff0c;但是俗话说"基础不牢&#xff0c;地动山摇"&#xff0c;所以还请大家静下心来进行学习 来翻译一下是什么意思&#…

毕设 基于机器视觉的驾驶疲劳检测系统(源码+论文)

文章目录 0 前言1 项目运行效果2 课题背景3 Dlib人脸检测与特征提取3.1 简介3.2 Dlib优点 4 疲劳检测算法4.1 眼睛检测算法4.2 打哈欠检测算法4.3 点头检测算法 5 PyQt55.1 简介5.2相关界面代码 6 最后 0 前言 &#x1f525;这两年开始毕业设计和毕业答辩的要求和难度不断提升…