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

性能对比表

实现类查找插入删除有序性线程安全
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;@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));

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

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

相关文章

[最全总结]城市灾害应急管理系统

城市灾害应急管理集成系统 | 国家重点研发政府间合作项目 Vue+ElementUI+Bpmn+Cesium+Java SpringBoot 项目描述 在智慧城市战略背景下,项目面向内涝、团雾和火灾等灾害,开发了集灾害模型集成模拟、场景可视化与应急预案管理于一体的系统,系统各子模块进行软件功能测试,测…

QtWidgets模块功能及架构解析

QtWidgets 是 Qt 框架中用于创建传统桌面应用程序图形用户界面(GUI)的核心模块。在 Qt 6.0 中&#xff0c;QtWidgets 模块继续提供丰富的 UI 组件和功能&#xff0c;尽管 Qt 正在向 QML 方向演进&#xff0c;但 QtWidgets 仍然是许多桌面应用程序的基础。 一、主要功能 基础窗…

grep、wc 与管道符快速上手指南

&#x1f3af; Linux grep、wc 与管道符快速上手指南&#xff1a;从入门到实用 &#x1f4c5; 更新时间&#xff1a;2025年6月7日 &#x1f3f7;️ 标签&#xff1a;Linux | grep | wc | 管道符 | 命令行 文章目录 前言&#x1f31f; 一、grep、wc 和管道符简介1.核心功能2.核心…

C++11 右值引用:从入门到精通

文章目录 一、引言二、左值和右值&#xff08;一&#xff09;概念&#xff08;二&#xff09;区别和判断方法 三、左值引用和右值引用&#xff08;一&#xff09;左值引用&#xff08;二&#xff09;右值引用 四、移动语义&#xff08;一&#xff09;概念和必要性&#xff08;二…

java复习 04

心情复杂呢&#xff0c;现在是6.7高考第一天&#xff0c;那年今日此时此刻我还在考场挣扎数学&#xff0c;虽然结果的确很糟糕&#xff0c;&#xff0c;现在我有点对自己生气明明很多事情待办确无所事事没有目标&#xff0c;不要忘记曾经的自己是什么样子的&#xff0c;去年今日…

从零开始搭建 Pytest 测试框架(Python 3.8 + PyCharm 版)

概述 在软件开发中&#xff0c;自动化测试是确保代码质量的重要方式。而 Pytest 是一个功能强大且易于上手的 Python 测试框架&#xff0c;非常适合初学者入门。 本文将带你一步步完成&#xff1a; 安装和配置 Pytest在 PyCharm 中搭建一个清晰的测试项目结构 准备工作 在…

用电脑通过网口控制keysight示波器

KEYSIGHT示波器HD304MSO性能 亮点: 体验 200 MHz 至 1 GHz 的带宽和 4 个模拟通道。与 12 位 ADC 相比,使用 14 位模数转换器 (ADC) 将垂直分辨率提高四倍。使用 10.1 英寸电容式触摸屏轻松查看和分析您的信号。捕获 50 μVRMS 本底噪声的较小信号。使用独有区域触摸在几秒…

Java Smart 系统题库试卷管理模块设计:从需求到开发的实战指南

在教育信息化不断推进的背景下&#xff0c;高效的题库及试卷管理系统至关重要。Java Smart 系统中的题库及试卷管理模块&#xff0c;旨在为教师提供便捷的试题录入、试卷生成与管理功能&#xff0c;同时方便学生在线练习与考试。本文将详细介绍该模块的设计思路与核心代码实现。…

PDF图片和表格等信息提取开源项目

文章目录 综合性工具专门的表格提取工具经典工具 综合性工具 PDF-Extract-Kit - opendatalab开发的综合工具包&#xff0c;包含布局检测、公式检测、公式识别和OCR功能 仓库&#xff1a;opendatalab/PDF-Extract-Kit特点&#xff1a;功能全面&#xff0c;包含表格内容提取的S…

git小乌龟不显示图标状态解决方案

第一步 在开始菜单的搜索处&#xff0c;输入regedit命令&#xff0c;打开注册表。 第二步 在注册表编辑器中&#xff0c;找到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers 这一项。 第三步 让Tortoise相关的项目排在前…

Windows平台RTSP/RTMP播放器C#接入详解

大牛直播SDK在Windows平台下的RTSP、RTMP播放器模块&#xff0c;基于自研高性能内核&#xff0c;具备极高的稳定性与行业领先的超低延迟表现。相比传统基于FFmpeg或VLC的播放器实现&#xff0c;SmartPlayer不仅支持RTSP TCP/UDP自动切换、401鉴权、断网重连等网络复杂场景自适应…

题海拾贝:P1091 [NOIP 2004 提高组] 合唱队形

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

Python控制台输出彩色字体指南

在Python开发中&#xff0c;有时我们需要在控制台输出彩色文本以提高可读性或创建更友好的用户界面。本文将介绍如何使用colorama库来实现这一功能。 为什么需要彩色输出&#xff1f; 提高可读性&#xff1a;重要信息可以用不同颜色突出显示更好的用户体验&#xff1a;错误信息…

chili3d 笔记17 c++ 编译hlr 带隐藏线工程图

这个要注册不然emscripten编译不起来 --------------- 行不通 ---------------- 结构体 using LineSegment std::pair<gp_Pnt, gp_Pnt>;using LineSegmentList std::vector<LineSegment>; EMSCRIPTEN_BINDINGS(Shape_Projection) {value_object<LineSegment&g…

【Java开发日记】说一说 SpringBoot 中 CommandLineRunner

目录 1、CommandLineRunner SpringBoot中CommandLineRunner的作用 简单例子 多个类实现CommandLineRunner接口执行顺序的保证 通过实现Ordered接口实现控制执行顺序 通过Order注解实现控制执行顺序 Order 作用 2、ApplicationRunner 3、传递参数 4、源码跟踪 run()方…

为什么React列表项需要key?(React key)(稳定的唯一标识key有助于React虚拟DOM优化重绘大型列表)

文章目录 1. **帮助 React 识别列表项的变化**2. **性能优化**3. **避免组件状态混乱**4. **为什么使用 rpid 作为 key**5. **不好的做法示例**6. **✅ 正确的做法** 在 React 中添加 key{item.rpid} 是非常重要的&#xff0c;主要有以下几个原因&#xff1a; 1. 帮助 React 识…

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>());

DeepSeek09-open-webui使用

Open WebUI 完全指南&#xff1a;从安装到知识库搭建与异常处理 最后更新&#xff1a;2025年6月7日 | 适用版本&#xff1a;Open WebUI v0.6.x 一、安装部署 1.1 系统要求 **Python 3.12 **&#xff08;严格版本要求&#xff0c;更高版本3.13不兼容&#xff09;Node.js 20.x内…

前端面试五之vue2基础

1.属性绑定v-bind&#xff08;&#xff1a;&#xff09; v-bind 是 Vue 2 中用于动态绑定属性的核心指令&#xff0c;它支持多种语法和用法&#xff0c;能够灵活地绑定 DOM 属性、组件 prop&#xff0c;甚至动态属性名。通过 v-bind&#xff0c;可以实现数据与视图之间的高效同…

408第一季 - 数据结构 - 栈与队列

栈 闲聊 栈是一个线性表 栈的特点是后进先出 然后是一个公式 比如123要入栈&#xff0c;一共有5种排列组合的出栈 栈的数组实现 这里有两种情况&#xff0c;&#xff0c;一个是有下标为-1的&#xff0c;一个没有 代码不用看&#xff0c;真题不会考 栈的链式存储结构 L ->…