• java集合类史上最细讲解 - Map篇


    1.Map接口介绍

    Map用于保存具有映射关系的数据:Key - Value

    对于Set,底层其实依然是一个Map,但是Set选择不使用Value,也就是Set的Value值始终是一个常量😁

    Map中的Key和Value可以是任何类型的数据,会封装到HashMap$Node对象中

    Map中的Key不能重复,但是Value可以重复,当有相同的Key时,等价与替换操作😀


    2.Map接口分析

    存放Map键值对是在HashMap$Node

    tab[i] = newNode(hash, key, value, null);
    
    --
    
    Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
        return new Node<>(hash, key, value, next);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    那么这个Node节点的数据类型是什么样的呢?

    我们来看一下源代码:(其还实现了Entry接口)

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;  // 存放hash值
        final K key;  // 存放key值
        V value;  // 存放Value值
        Node<K,V> next;  // 存放下一个个节点,以形成链表结构
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    k-v为了方便程序员的遍历,还会创建一个EntrySet集合,该集合存放的元素类型是Entry,而一个Entry对象含有k,v,但是本质上这里的k-v值还是指向一个Node节点中的数据,也就是这里的k-v存放的依然是地址数据📕

    // k-v存在有EntrySet的一个指向
    Set set = map.entrySet();
    System.out.println(set.getClass());
    --------------------
    输出:
    class java.util.HashMap$EntrySet
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    那么,这个方便程序员遍历的特性是如何体现的呢?

    原因是Map.Entry提供了两个非常重要的方法:K getKey(); V getValue();。所以我们可以通过如下的方式进行遍历Map:

    Set set = map.entrySet();
    System.out.println(set.getClass());
    for (Object obj : set) {
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey());
        System.out.println(entry.getValue());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    那怎么证明Entry里面存放的k-v只是地址的指向呢?很简单

    通过debug,我们先来看一下Map中存放的数据,其no2这个键的地址是@727

    在这里插入图片描述

    再来看一下set中no2键的地址,一模一样:🎉

    在这里插入图片描述


    3.Map接口方法

    代码示例:

    Map map = new HashMap();
    // 添加键值对
    map.put("no1","dahe");
    map.put("no2","zhangsan");
    // Key重复会进行替换
    map.put("no1","lisi");
    System.out.println(map);
    
    // 根据键删除映射关系
    map.remove("no1");
    System.out.println(map);
    // 根据key得到值
    Object no2 = map.get("no2");
    System.out.println(no2);
    // 获取键值对数量
    System.out.println(map.size());
    // 判空
    System.out.println(map.isEmpty());
    // 清空
    // map.clear();
    // 查找键是否存在
    System.out.println(map.containsKey("ok"));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    4.Map遍历方式

    第一式:取出所有的key,通过key取出对应的value

    // 取出所有的key,通过key取出对应的value
    Set keySet = map.keySet();
    for (Object o : keySet) {
        System.out.println(o);
        System.out.println(map.get(o));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    第二式:把所有的value值取出

    // 把所有的value值取出
    Collection values = map.values();
    for (Object value : values) {
        System.out.println(value);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    第三式:通过EntrySet来获取 k-v

    // 通过EntrySet来获取 k-v
    Set entrySet1 = map.entrySet();
    for (Object o : entrySet1) {
        // 将entry 转成 Map.Entry
        Map.Entry m = (Map.Entry) o;
        System.out.println(m.getKey());
        System.out.println(m.getValue());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    ai批量剪辑矩阵无人直播一站式托管系统源头技术开发
    Java设计模式之模板方法模式
    【Linux】Http协议
    并行与分布式 第七章 体系结构 上
    易周金融 | Q1保险行业活跃人数8688.67万人 19家支付机构牌照被注销
    Text embedding 模型总结
    【算法|习题总结】算法分析与计算复杂性在线测试Ⅰ
    vue 项目启动后一直不断的刷新停不下来
    C/S架构学习之多线程实现TCP并发服务器
    45 Float.NaN == Float.NaN 为 false 是怎么实现的?
  • 原文地址:https://blog.csdn.net/Gherbirthday0916/article/details/125935433