第11篇:Java Map集合详解,HashMap底层原理、哈希冲突、JDK1.8优化、遍历方式彻底吃透

前面我们学完了 Collection单列集合:List、Set。

今天正式进入Java集合最重要、面试问得最多、工作用得最频繁 的集合:Map双列集合

如果说 List 是一排柜子 、Set 是独立储物柜 ; 那 Map 就是身份证一个编号(Key)对应一个人(Value)

Map 全部以 键值对(Key-Value) 方式存储数据,这是和之前所有集合最大的区别。

本篇重点讲解 HashMap(重中之重),通俗拆解底层哈希表、哈希冲突、JDK1.7与JDK1.8区别、扩容机制、红黑树转换、遍历方式。全篇没有难懂源码,新手一次性看懂。

本篇核心学习目标:

  • 理解Map集合特点、键值对存储结构

  • 精通HashMap底层结构、存储流程

  • 弄懂哈希冲突、怎么解决冲突

  • 吃透JDK1.8优化(链表转红黑树)

  • 掌握HashMap四种遍历方式

  • 分清HashMap、TreeMap、HashTable区别

  • 背熟高频Map面试题


一、Map集合是什么?能干什么?

1.1 Map存储结构

Map = 键(Key) + 值(Value)

生活举例:

  • 手机号(Key) = 联系人姓名(Value)

  • 学号(Key) = 学生信息(Value)

  • IP地址(Key) = 地理位置(Value)

1.2 Map核心特点(必背)

  1. 键(Key)唯一、不可重复

  2. 值(Value)可重复

  3. 一个键只能对应一个值

  4. 无序、无索引

  5. 键重复会覆盖旧值

1.3 Map常用实现类

实现类 底层结构 顺序 线程安全 使用场景
HashMap 哈希表 无序 不安全 日常开发首选
TreeMap 红黑树 按键排序 不安全 需要排序
HashTable 哈希表 无序 安全 老旧、已淘汰

二、Map常用方法(工作天天写)

2.1 通用基础方法

java 复制代码
put(key,value)        // 添加/覆盖元素
get(key)               // 根据键取值
remove(key)            // 根据键删除
containsKey(key)       // 判断键是否存在
containsValue(value)   // 判断值是否存在
size()                 // 获取键值对个数
clear()                // 清空集合
keySet()               // 获取所有键
values()               // 获取所有值
entrySet()             // 获取键值对对象

2.2 代码基础演示

java 复制代码
import java.util.HashMap;
import java.util.Map;

public class MapDemo {
    public static void main(String[] args) {
        Map<String,String> map = new HashMap<>();

        // 添加数据
        map.put("001","张三");
        map.put("002","李四");
        map.put("001","张三三"); // 键重复,覆盖旧值

        // 查询
        System.out.println(map.get("001")); // 输出:张三三

        // 删除
        map.remove("002");

        System.out.println(map);
    }
}

重点:键重复不会报错,直接覆盖旧数据!


三、HashMap底层原理(面试必考核心)

3.1 底层结构演变

JDK1.7:数组 + 单向链表
JDK1.8:数组 + 单向链表 + 红黑树(重点)

3.2 初始化参数(必须记住)

  • 默认初始容量:16

  • 加载因子:0.75

  • 扩容阈值:16 * 0.75 = 12

  • 链表转红黑树条件:链表长度>8 && 数组长度>=64

  • 红黑树退化成链表:节点小于6

3.3 HashMap存储流程(通俗大白话)

  1. 首次put,创建长度为16的数组

  2. 通过key计算hash值,定位数组下标

  3. 下标位置为空:直接存入

  4. 下标位置有数据:发生哈希冲突

  5. 冲突后:挂在链表尾部(JDK1.8尾插法)

  6. 链表过长:长度超过8,数组达标64,转为红黑树

  7. 达到阈值12,自动扩容为原来2倍

3.4 什么是哈希冲突?

不同的Key,经过哈希算法算出相同数组下标,就叫哈希冲突。

HashMap三种解决冲突方式:
  1. 哈希算法(尽量分散)

  2. 链表法(冲突后挂链表)

  3. 红黑树(超长链表优化查询)

3.5 JDK1.8重大优化(面试高频)

  • 头插法 改为尾插法(避免循环链表死链)

  • 新增红黑树,查询速度大幅提升

  • 优化hash算法,减少冲突概率


四、HashMap四种遍历方式(工作必写)

4.1 方式一:遍历键(keySet)

java 复制代码
for (String key : map.keySet()) {
    System.out.println(key + "=" + map.get(key));
}

4.2 方式二:遍历值(values)

java 复制代码
for (String value : map.values()) {
    System.out.println(value);
}

4.3 方式三:键值对遍历(entrySet,推荐最快)

java 复制代码
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey()+"="+entry.getValue());
}

4.4 方式四:Lambda遍历(简洁)

java 复制代码
map.forEach((k,v)-> System.out.println(k+"="+v));

开发最优遍历:entrySet 效率最高,没有重复查询。


五、HashMap、HashTable、ConcurrentHashMap区别

这是面试必问三连,直接背下表:

集合 线程安全 效率 key、value是否允许null 底层
HashMap 不安全 最快 key最多一个null,value任意null 哈希表
HashTable 安全 都不允许null 哈希表
ConcurrentHashMap 安全 较快 不允许null 分段锁哈希表

口诀:单线程HashMap,多线程ConcurrentHashMap,HashTable彻底不用。


六、新手高频易错坑(避坑指南)

  1. HashMap键重复直接覆盖,不会报错

  2. HashMap允许一个key为null,多个value为null

  3. JDK1.8链表是尾插法,不是头插

  4. 链表转红黑树必须同时满足两个条件,不是到8就转

  5. HashMap线程不安全:多线程put可能数据丢失

  6. 不要在循环中频繁keySet遍历取值,效率低,优先entrySet


七、本篇总结

本篇是集合框架最难、最重要的一篇,你必须牢牢记住:

  • Map是双列集合,键唯一、值重复、无序无索引

  • HashMap底层:数组+链表+红黑树

  • 默认容量16、加载因子0.75、阈值12

  • 哈希冲突:链表挂载,过长转红黑树

  • 四种遍历,优先entrySet

  • 单线程HashMap,多线程ConcurrentHashMap

相关推荐
还得是你大哥1 小时前
Java互联网医院管理系统源码SpringBoot
java·spring boot·vue
阿维的博客日记2 小时前
怎么用ThreadLocal解决用户的登录上下文
java·juc
Dicky-_-zhang2 小时前
容器编排实战:Docker与Kubernetes对比选型与落地实践
java·jvm
benpaodeDD2 小时前
视频10,11,12,13——java程序的加载与执行,安装jdk
java·开发语言
一颗牙牙3 小时前
安装mmcv
开发语言·python·深度学习
大空大地20263 小时前
C#高级语法总结
开发语言·c#
ytttr8733 小时前
DSP 28335 CAN总线通信程序
开发语言·stm32·单片机
数字化顾问3 小时前
(122页PPT)数字化架构的演进和治理(附下载方式)
java·运维·架构
XiYang-DING3 小时前
【Java SE】JVM
java·开发语言·jvm