news 2026/9/6 18:29:45

Java Map学习笔记:HashMap、LinkedHashMap 与 TreeMap 的核心使用与区别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java Map学习笔记:HashMap、LinkedHashMap 与 TreeMap 的核心使用与区别

Java内置的集合框架,除了提供Collection单列集合外,还提供所谓双列集合Map,即所谓存储“键值对”的集合。键和值是两个对象,而键值对在Java中称为entry。

与Collection相似,Map是一个接口,有HashMap、LinkedHashMap和TreeMap三种实现类,这三种实现类与Set的三种实现类(HashSet、LinkedHashSet和TreeSet)在底层实现上相同。实际上,Map只是比Set增加了一个“值对象”。准确来说,HashSet的内部实现基于 HashMap,将其值视为一个固定值。因此,Map具有与Set相似特点:不保证顺序、键不可重复(但值可重复)、不可索引。

Map的方法与Set也很相似,但是额外多了有关值的方法。Map常见方法如下:

Vput(Kkey,Vvalue);// 添加键值对,如果键存在会返回旧值,如果键不存在则返回nullVremove(Objectkey);// 删除键值对,返回旧值。若键不存在则返回nullbooleanremove(Objectkey,Objectvalue);// 删除指定键值对voidclear();// 清空MapVget(Objectkey);// 获取指定键的值booleancontainsKey(Objectkey);// 是否包含键booleancontainsValue(Objectvalue);// 是否包含值intsize();// 元素数量booleanisEmpty();// 是否为空

对常见方法的代码演示如下:

publicclassDemo0{publicstaticvoidmain(String[]args){// 创建Map集合对象Map<String,String>map=newHashMap<>();// boolean isEmpty(); 判断集合是否为空System.out.println(map.isEmpty());// true// V put(K key, V value); 添加键值对,如果键存在会返回旧值,同时覆盖旧值,如果键不存在则返回nullSystem.out.println(map.put("郭靖","黄蓉"));// nullSystem.out.println(map.put("杨过","小龙女"));// nullSystem.out.println(map.put("韦小宝","沐剑屏"));// nullSystem.out.println(map.put("韦小宝","阿珂"));// 沐剑屏System.out.println(map);// {郭靖=黄蓉, 杨过=小龙女, 韦小宝=阿珂}// int size(); 获取键值对数量System.out.println(map.size());// 3System.out.println(map.isEmpty());// false// boolean containsKey(Object key); 判断集合中是否包含指定的键System.out.println(map.containsKey("郭靖"));// trueSystem.out.println(map.containsKey("小龙女"));// false// boolean containsValue(Object value); 判断集合中是否包含指定的值System.out.println(map.containsValue("阿珂"));// trueSystem.out.println(map.containsValue("沐剑屏"));// false// V remove(Object key); 删除键值对,返回旧值。若键不存在则返回nullSystem.out.println(map.remove("郭靖"));// 黄蓉System.out.println(map.remove("小龙女"));// null}}

Map的遍历有三种方式:

  1. 通过键找值:获取Map中的所有key为新Set,再通过key找到value。
  2. 通过键值对:获取Map中的键值对对象成一个新Set,再遍历键值对对象找key、value。
  3. 使用foreach方法用lamda表达式
publicclassDemo1{publicstaticvoidmain(String[]args){// 创建Map集合Map<String,String>map=newHashMap<>();// 添加元素map.put("郭靖","黄蓉");map.put("杨过","小龙女");map.put("韦小宝","沐剑屏");// 遍历方法1: 通过键找值:获取Map中的所有key为新单列集合,再通过key找到value。Set<String>keys=map.keySet();// keySet()方法获取Map中的所有key集合for(Stringkey:keys){Stringvalue=map.get(key);// get(key)方法通过key找到valueSystem.out.println(key+"="+value);}System.out.println("---------分割线-----------");// 遍历方法2: 通过键值对:获取Map中的键值对对象成一个新单列集合,再遍历键值对对象找key、value。Set<Map.Entry<String,String>>entries=map.entrySet();// entrySet()方法获取Map中的键值对对象集合for(Map.Entry<String,String>entry:entries){Stringkey=entry.getKey();// Entry对象的getKey()方法获取keyStringvalue=entry.getValue();// Entry对象的getValue()方法获取valueSystem.out.println(key+"="+value);}System.out.println("---------分割线-----------");// 遍历方法3: 通过foreach方法map.forEach((key,value)->System.out.println(key+"="+value));}}

HashMap

HashMap是Map的实现类,底层使用哈希表。

HashMap与HashSet相似,HashSet节点Node中存储的内容是元素本身,而HashMap存储的内容是键值对对象,又称为Entry对象。

HashMap的元素插入逻辑:

  1. 将键和值两个对象,组成一个键值对Entry对象
  2. 用键调用hashCode()方法,计算键的哈希值
  3. 通过哈希值和哈希表数组的长度,计算数组索引值
  4. 若数组为null,则存储键值对对象
  5. 若数组不为null,则调用equals()方法,逐一判断链表中已存在的键值对的键,是否相等
  6. 若键相同,则覆盖键值对对象
  7. 若链表中的键都不同,则最后插入到链表尾部。

因此,若用HashMap,与HashSet相似,需要重写键类的hashCode()和equals()方法。

LinkedHashMap

LinkedHashMap是Map的实现类,底层使用哈希表。

LinkedHashMap与HashMap的关系,就跟LinkedHashSet与HashSet的关系相似,LinkedHashMap是在HashMap的节点基础上,增加了指向上一个插入元素Entry对象的节点和指向下一个插入元素Entry对象的节点。

因此,LinkedHashMap特点是有序、键不重复、不可索引。如下可以看出,遍历获取的顺序与插入顺序相同:

publicclassDemo2{publicstaticvoidmain(String[]args){// 创建一个Map集合对象Map<Student,String>map=newLinkedHashMap<>();// 添加三个元素map.put(newStudent("张三",18),"成都");map.put(newStudent("李四",19),"上海");map.put(newStudent("王五",20),"北京");// 遍历键值对for(Map.Entry<Student,String>entry:map.entrySet()){System.out.println(entry.getKey()+"="+entry.getValue());}}}
Student{name='张三',age=18}=成都 Student{name='李四',age=19}=上海 Student{name='王五',age=20}=北京 进程已结束,退出代码为0

TreeMap

TreeMap是Map的实现类,底层使用红黑树。

TreeMap与TreeSet相似,HashSet节点Node中存储的内容是元素本身,而HashMap存储的内容是键值对对象,又称为Entry对象。

树这一数据结构要求存储的元素需要能够比较,因此TreeMap存储的键值对对象的键也需要支持比较。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/3 5:26:14

如何用cgroups实现精细化Docker资源控制?一篇讲透底层原理

第一章&#xff1a;Docker资源限制概述在容器化应用部署中&#xff0c;资源的合理分配与隔离是保障系统稳定性与安全性的关键。Docker 提供了灵活的资源限制机制&#xff0c;允许用户对容器的 CPU、内存、磁盘 I/O 等核心资源进行精细化控制&#xff0c;避免单个容器过度占用宿…

作者头像 李华
网站建设 2026/9/5 14:14:47

C++车辆管理系统[2026-01-05]

C车辆管理系统[2026-01-05] 题目 4 “车辆管理系统设计” 1、问题描述 车辆管理系统主要负责各种车辆的常规信息管理工作。 系统中的车辆主要有大客车、小轿车和卡车。每种车辆有车辆编号、车牌号、车辆制造公司、车辆购买时间、车辆型号&#xff08;大客车、小轿车和卡车&…

作者头像 李华
网站建设 2026/9/3 5:26:18

容器CPU飙升却找不到原因?Docker性能监控必须关注的7个信号

第一章&#xff1a;容器CPU飙升却找不到原因&#xff1f;Docker性能监控必须关注的7个信号在Docker环境中&#xff0c;容器CPU使用率突然飙升却难以定位根源是常见运维难题。问题可能源自应用逻辑、资源限制配置不当或底层系统争用。通过监控关键性能信号&#xff0c;可快速缩小…

作者头像 李华
网站建设 2026/9/3 13:09:57

Artix-7片上存储方案选择:BRAM应用解析一文说清

Artix-7片上存储怎么选&#xff1f;BRAM实战全解析&#xff1a;从原理到避坑一文讲透为什么你的FPGA设计总卡在延迟和资源上&#xff1f;你有没有遇到过这样的场景&#xff1a;数据流眼看着要“爆”了&#xff0c;但处理模块却慢半拍&#xff1b;逻辑综合报错说LUT不够用&#…

作者头像 李华
网站建设 2026/9/4 11:04:34

【Docker日志监控】:ELK+Filebeat 实现日志自动收集的完整路径

第一章&#xff1a;Docker日志收集的核心挑战与架构演进在容器化应用广泛部署的背景下&#xff0c;Docker日志的高效收集与管理成为运维体系中的关键环节。传统虚拟机时代的集中式日志方案难以应对容器动态性强、生命周期短、实例数量庞大的特点&#xff0c;由此催生了新的日志…

作者头像 李华
网站建设 2026/9/5 9:48:15

RISC-V五级流水线CPU内存子系统在FPGA中的搭建教程

搭建RISC-V五级流水线CPU的内存子系统&#xff1a;从零开始的FPGA实战指南你有没有试过在FPGA上跑一个自己写的RISC-V CPU&#xff0c;结果卡在第一条指令&#xff1f;或者程序能启动&#xff0c;但一碰到数据访问就乱码、死锁甚至流水线“堵车”&#xff1f;别急——这大概率不…

作者头像 李华