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常见方法如下:

java 复制代码
V put(K key, V value);           // 添加键值对,如果键存在会返回旧值,如果键不存在则返回null
V remove(Object key);             // 删除键值对,返回旧值。若键不存在则返回null
boolean remove(Object key, Object value); // 删除指定键值对
void clear();                     // 清空Map
V get(Object key);                // 获取指定键的值
boolean containsKey(Object key);  // 是否包含键
boolean containsValue(Object value); // 是否包含值
int size();                       // 元素数量
boolean isEmpty();                // 是否为空

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

java 复制代码
public class Demo0 {  
    public static void main(String[] args) {  
        // 创建Map集合对象  
        Map<String, String> map = new HashMap<>();  
  
        // boolean isEmpty(); 判断集合是否为空  
        System.out.println(map.isEmpty()); // true  
  
        // V put(K key, V value); 添加键值对,如果键存在会返回旧值,同时覆盖旧值,如果键不存在则返回null  
        System.out.println(map.put("郭靖", "黄蓉")); // null  
        System.out.println(map.put("杨过", "小龙女")); // null  
        System.out.println(map.put("韦小宝", "沐剑屏")); // null  
        System.out.println(map.put("韦小宝", "阿珂")); // 沐剑屏  
  
        System.out.println(map); // {郭靖=黄蓉, 杨过=小龙女, 韦小宝=阿珂}  
  
        // int size(); 获取键值对数量  
        System.out.println(map.size()); // 3  
        System.out.println(map.isEmpty()); // false  
  
        // boolean containsKey(Object key); 判断集合中是否包含指定的键  
        System.out.println(map.containsKey("郭靖")); // true  
        System.out.println(map.containsKey("小龙女")); // false  
  
        // boolean containsValue(Object value); 判断集合中是否包含指定的值  
        System.out.println(map.containsValue("阿珂")); // true  
        System.out.println(map.containsValue("沐剑屏")); // false  
  
        // V remove(Object key); 删除键值对,返回旧值。若键不存在则返回null  
        System.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表达式
java 复制代码
public class Demo1 {  
    public static void main(String[] args) {  
        // 创建Map集合  
        Map<String, String> map = new HashMap<>();  
  
        // 添加元素  
        map.put("郭靖", "黄蓉");  
        map.put("杨过", "小龙女");  
        map.put("韦小宝", "沐剑屏");  
  
        // 遍历方法1: 通过键找值:获取Map中的所有key为新单列集合,再通过key找到value。  
        Set<String> keys = map.keySet(); // keySet()方法获取Map中的所有key集合  
        for (String key : keys) {  
            String value = map.get(key); // get(key)方法通过key找到value  
            System.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) {  
            String key = entry.getKey(); // Entry对象的getKey()方法获取key  
            String value = entry.getValue(); // Entry对象的getValue()方法获取value  
            System.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特点是有序、键不重复、不可索引。如下可以看出,遍历获取的顺序与插入顺序相同:

java 复制代码
public class Demo2 {  
    public static void main(String[] args) {  
        // 创建一个Map集合对象  
        Map<Student, String> map = new LinkedHashMap<>();  
  
        // 添加三个元素  
        map.put(new Student("张三", 18), "成都");  
        map.put(new Student("李四", 19), "上海");  
        map.put(new Student("王五", 20), "北京");  
  
        // 遍历键值对  
        for (Map.Entry<Student, String> entry : map.entrySet()) {  
            System.out.println(entry.getKey() + "=" + entry.getValue());  
        }  
    }  
}
shell 复制代码
Student{name='张三', age=18}=成都
Student{name='李四', age=19}=上海
Student{name='王五', age=20}=北京

进程已结束,退出代码为 0

TreeMap

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

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

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

相关推荐
腻害兔4 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
克里斯蒂亚诺更新5 小时前
ruoyi角色权限的对应关系
笔记
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117768 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao8 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
维天说9 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
破碎的南瓜9 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
Zane199410 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端