11_6、Java集合之Map接口(包括HashMap在内的子接口)的使用

news2025/7/10 4:18:41

一、引入

Map与Collection并列存在。用于保存具有映射关系的数据:key-value (双列集合框架),Map 中的 key 和 value 都可以是任何引用类型的数据 。Map 中的 key 用Set来存放,不允许重复,即同一个 Map 对象所对应 的类,须重写hashCode()和equals()方法 。key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到 唯一的、确定的 value 。Map接口的常用实现类:HashMap、TreeMap、LinkedHashMap和 Properties。其中,HashMap是 Map 接口使用频率最高的实现类 。

二、常用实现类结构

1、Map:双列结构,存储具key-value特点的数据。

可以类比:“数学中的函数” y = f(x);

1.1、HashMap:作为Map接口的主要实现类。线程不安全的,效率高;可以存储null的key和value

1.1.1、LinkedHashMap:保证在遍历Map的元素时,可以照添加的顺序进行遍历。

原因:在HashMap的基础上,添加了一对指针,分别指向前一个元素和后一个元素。对于频繁的遍历操作时,此类比HashMap的效率更高

1.2、TreeMap:保证照添加的key-value对进行排序,实现顺序遍历。一般考虑使用key的值进行自然排序或定制排序。底层使用红黑树存储数据。

1.3、Hashtable:作为古老实现类。线程安全的,效率低。不能存储null的key和value

1.3.1、Properties:常用来处理配置文件,其key和value都是String类型。

2、HashMap的底层结构:

①、 jdk 7 及以前:数组+链表

②、jdk8:数组+链表+红黑树

3、经典面试题(高频)

①、HashMap的底层实现原理?

②、HashMap与Hashtable的异同?

三、存储结构的理解

Map中的key-value结构理解

1、Map中的key:无序的、不可重复的。使用Set存储。—>key所在的类必须重写equals()和hashCode()(以HashMap为例)。

2、Map中的value:无序的,可重复的。使用Collection存储。—>value所在的类必须重写equals()。

一个键值对:key-value构成一个Entry对象。Map中的entry:无序的,不可重复的,使用Set存储。

图示:

四、常用方法

1、添加:put(Object key,Object value)

        Map map = new HashMap();
        //put()
        map.put("AA",123);//添加
        map.put(45,12);
        map.put("CC",96);
        

        Map map1 = new HashMap();
        map1.put("GG",96);
        map1.put("FF",96);
        //putAll(Map m)
        map.putAll(map1);
        System.out.println(map);

2、删除:remove(Object key)

        //remove(Object key)
        map.remove("GG");
        System.out.println(map);

3、更改:put(Object key,Object value)

        map.put("AA",88);//替换覆盖

4、查询:get(Object key);

        //Object get(Object key)
        System.out.println(map.get("AA"));//123

5、长度:size()

        System.out.println(map.size());

6、遍历:keySet() \ values() \ entrySet()

/*
    元视图操作的方法:
    Set keySet():返回所有key构成的Set集合
    Collection values():返回所有value构成的Collection集合
    Set entrySet():返回所有key-value对构成的Set集合
     */
    @Test
    public void test5() {
        Map map = new HashMap();
        map.put("AA", 123);//添加
        map.put(45, 12);
        map.put("CC", 96);

        //Set keySet()
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println();
        //Collection values()
        Collection values = map.values();
        for(Object obj : values){
            System.out.println(obj);
        }
        System.out.println();

        //Set entrySet()
        Set set1 = map.entrySet();
        //方式1
        Iterator iterator1 = set1.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            Map.Entry entry = (Map.Entry) obj;
            Object key = entry.getKey();
            Object value = entry.getValue();
            System.out.println(key  + "————>" + value);

        }
        System.out.println();
        //方式2
        Set set2 = map.keySet();
        Iterator iterator2 = set2.iterator();
        while(iterator2.hasNext()){
            Object key = iterator2.next();
            Object value = map.get(key);
            System.out.println(key + "===" + value);
        }
    }

五、内存结构说明(难点)

1、HashMap在jdk7中实现原理:

1.1、底层实现原理:

Map map = new HashMap();

底层创建了一个长度为16的一维数组 Entry[] table

... 此时可能已经调用过一次或多次put...

map.put(key1,value1);

首先,调用key1所在类的hashCode()方法,计算出key1的哈希值,再通过某种算法确定key1的索引:

如果当前数组索引上没有储存元素,那么key1-value1存储成功。—>情况1

如果当前数组索引上已经存储元素(存储一个或多个数据(以链表形式存在)),那么比较key1与一个或多个已存在的数据的哈希值:

如果key1与其他一个或多个数据的哈希值不相同,那么key1-value1以链表的形式添加成功。—>情况2

如果key1与某一个数据(key2-value2)的哈希值相同,那么就调用key1.equals(key2):

如果equals()返回的false,那么key1-value1以链表的形式添加成功。—>情况3

如果equals()返回true,那么用value1替换value2的数据。(此时的put方法具有更新数据的作用)。

1. 2、补充

对于情况2与情况3,此时的key1-value1与其它数据以链表的方式存储。

1.3、扩容机制

在不断的添加过程中,涉及到扩容机制:当超出临界值(且要存储的位置非空时)扩容至原有数组长度的2倍,并将原有的数据复制到新数组。

2、HashMap在jdk8中相较于jdk7在底层实现方面的不同:

2.1、new HashMap();时,底层没有创建长度为16的数组。

2.2、底层的存储数组为Node[],而并非Entry[]。

2.3、首次调用put方法时,会创建一个长度为16的Node[]数组。

2.4、jdk7中:数组+链表;jdk8中:数组+链表+红黑树 。

在HashMap中数组的某个索引上的以链表形式存在的元素个数 > 8 且当前数组长度 > 64时,此时,从索引上的所有元素改为红黑树存储。

3、HashMap底层典型属性的属性的说明:

3.1、DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16

3.2、DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75

3.3、threshold:扩容的临界值,=容量*填充因子 16*0.75 >=12

3.4、TREEIFY_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8

3.5、MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量。64

4、LinkedHashMap的底层实现源码:

static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;可以记录前一个和后一个元素,方便遍历集合
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }

保证在遍历Map的元素时,可以照添加的顺序进行遍历。

原因:在HashMap的基础上,添加了一对指针,分别指向前一个元素和后一个元素。对于频繁的遍历操作时,此类比HashMap的效率更高。

5、TreeMap的使用

TreeMap:要求添加进TreeMap中的key-value 中的key必须是同一个类的对象

通过key进行排序:自然排序、 定制排序。

要求:与TreeSet规则类似

5.1、自然排序

①提供用于添加元素测试的类:

public class User implements Comparable {
    private String name;
    private int age;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("User.equals()....");
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (age != user.age) return false;
        return Objects.equals(name, user.name);
    }

    @Override
    public String toString() {

        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

        @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    //按照姓名从大到小,年龄从小到大
    @Override
    public int compareTo(Object o) {
        if(o instanceof  User){
            User user = (User) o;
//            return -this.name.compareTo(user.name);
            int compare = -this.name.compareTo(user.name);
            if(compare != 0){
                return compare;
            }else{
                return Integer.compare(this.age,user.age);
            }
        }
        throw new RuntimeException("数据类型不匹配");
    }
}

②测试代码:

//自然排序
    @Test
    public void test1(){
        TreeMap map = new TreeMap();

        User u1 = new User("Tom",20);
        User u2 = new User("Jerry",38);
        User u3 = new User("Jack",22);
        User u4 = new User("Rose",18);

        map.put(u1,123);
        map.put(u2,456);
        map.put(u3,789);
        map.put(u4,963);

        Set set = map.entrySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            Map.Entry entry = (Map.Entry)obj;

            System.out.println(entry.getKey() + "--->" + entry.getValue());

        }
    }

测试结果:

5.2、定制排序

①测试代码:

//定制排序
    @Test
    public void test2(){
        TreeMap map = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof User && o2 instanceof User){
                    User u1 = (User) o1;
                    User u2 = (User) o2;
                    return -Integer.compare(u1.getAge(),u2.getAge());
                }
                throw new RuntimeException("数据类型不匹配");
            }
        });

        User u1 = new User("Tom",20);
        User u2 = new User("Jerry",38);
        User u3 = new User("Jack",22);
        User u4 = new User("Rose",18);

        map.put(u1,123);
        map.put(u2,456);
        map.put(u3,789);
        map.put(u4,963);

        Set set = map.entrySet();
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            Object obj = iterator.next();
            Map.Entry entry = (Map.Entry)obj;
            System.out.println(entry.getKey() + "--->" + entry.getValue());
        }
    }

测试结果:

6、使用Properties读取配置文件

Properties:常用来处理配置文件,其keyvalue都是String类型。

//Properties:常用来处理配置文件,其key和value都是String类型。
public static void main(String[] args)  {
    FileInputStream fis = null;
    try {
        Properties pro = new Properties();

        fis = new FileInputStream("jdbc.properties");
        pro.load(fis);//加载流对应文件

        String name = pro.getProperty("name");
        String password = pro.getProperty("password");

        System.out.println("name = " + name + ",password = " + password);
    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        if(fis != null){

            try {
                fis.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

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

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

相关文章

Android Studio生成自己的so库

一、创建Native项目 1、新建 Native 项目 1&#xff09;新建项目 选择最下面的 Native C 下一步即可 2&#xff09;填写项目信息 3&#xff09;选择C版本可以直接选择默认 2、下载并配置NDK及CMake 1&#xff09;进入Studio 设置 SDK 设置界面 这里选择需要的 NDK 和 CMake…

c++之 OpenGL(1)-安装与概述

目录概述&#xff46;&#xff45;&#xff44;&#xff4f;&#xff52;&#xff41;下安装编写OpenGL应用程序测试hello,world概述 OpenGL&#xff08;英语&#xff1a;Open Graphics Library&#xff0c;译名&#xff1a;开放图形库或者“开放式图形库”&#xff09;是用于…

Linux开发工具的使用(一)

文章目录Linux开发工具的使用&#xff08;一&#xff09;1. Linux软件包管理器yum1.1 查看软件1.2 下载软件1.3 卸载软件2.vim编辑器的介绍和使用2.1 vim的介绍2.2 vim的基本操作2.3 vim命令模式命令集(必须是命令模式下)2.3.1 移动光标2.3.2 删除文字2.3.3 复制文本内容2.3.4 …

C++ 不知树系列之二叉堆排序(递归和非递归实现上沉、下沉算法)

1. 前言 什么是二叉堆&#xff1f; 二叉堆是有序的 完全二叉树&#xff0c;在完全二叉树的基础上&#xff0c;二叉堆 提供了有序性特征&#xff1a; 二叉堆 的根结点上的值是整个堆中的最小值或最大值。 当根结点上的值是整个堆结构中的最小值时&#xff0c;此堆称为最小堆。…

xpath获取标签之间的文本内容

目前在学习xpath&#xff0c;需要取一个package信息&#xff0c;如图&#xff1a; 标题 "package"在span里面&#xff0c;比较方便取&#xff0c;用这个xpath就行&#xff1a; //div[idartikeltabelle]/table/tbody/tr[1]/td[2]/span[classinsertlabela and text()pa…

/mmcv/_ext.cpython-36m-x86_64-linux-gnu.so: undefined symbol: _ZN3c107Warning

报/mmcv/_ext.cpython-36m-x86_64-linux-gnu.so: undefined symbol: _ZN3c107Warning 就是mmcv或者mmcv-full编译有问题&#xff1b; 尝试了mmcv_full-1.7.1-cp36-cp36m-manylinux1_x86_64.whl pip 安装&#xff0c;都不是对应版本&#xff1b; 在安装mmcv或者mmcv-full都是无…

如何用PPT画出好看的科研图

前言 好看的科研图可以从前人的作品中进行借鉴&#xff0c;今天介绍2副精美的科研图以及他们在PPT中的绘制方法&#xff0c;话不多说&#xff0c;先摆上标准科研图 1. 黑色粗体边框以及淡填充颜色 黑色粗体边框和淡填充颜色真的让矩形一下子变得很有质感&#xff0c;在学习的…

VMware Fusion设置静态IP+端口转发(macOS)+内网穿透

很少有资料提到配置macOS上VMware Fusion的端口转发&#xff0c;因此我在这里进行了一些记录打开网络设置解锁并添加新的网络适配器只有新的网络适配器才允许配置转发&#xff0c;默认的不允许这样做。设置NAT转发虚拟机选择使用新创建的虚拟网络适配器Ubuntu配置静态IP/DNS服务…

linux xshell用户免密登录设置

最重要准备工作 ​编辑linux xshell用户免密登录设置步骤 1.在xshel进行密钥获取操作 2.创建mkdir ~/.ssh目录&#xff08;检查有没有这个目录&#xff0c;没有自己添加&#xff09; 3.在该目录创建authorized_keys目录。注意&#xff08;目录权限为600&#xff09; 4.将刚…

Android Studio arctic Fox(北极狐)导入openCV

Android studio arctic Fox在引入opencv的时候按照正常的File->New->Import Module操作时&#xff0c;出现无法点击“Next”和“Finish”的情况。如下图 所以我们使用另外的方法进行引入。 准备工作&#xff1a; 1&#xff0c;Android Studio 2&#xff0c;下载opencv…

纪念2022年11月软考高项(信息系统项目管理师)一次通过的经验随笔

一、备考背景2022年5月的浙江软考因为疫情防控原因临时取消&#xff0c;我离杭州买房又远了几分。众所周知&#xff0c;杭州是炒房投资客的香饽饽&#xff0c;即使主城区购房摇号制度不停打补丁&#xff0c;也难济于事。自住客为了与投资客抗衡&#xff0c;一靠社保&#xff0c…

新品做软文推广发布在哪些平台好?

新产品上市前后&#xff0c;会经历开发期、介绍期、成长期、成熟期、衰退期五个阶段&#xff0c;每个阶段都需要软文推广的助力&#xff01; 当一款新品上市前后往往会面临着无法打开市场、产品卖不出去等问题&#xff0c;这个时候软文推广就要做到位&#xff0c;除了文章撰写…

在centos7安装KubeSphere

节点准备 设置hostname hostnamectl set-hostname ks-m4 关闭防火墙 启动&#xff1a; systemctl start firewalld 关闭&#xff1a; systemctl stop firewalld 查看状态&#xff1a; systemctl status firewalld 开机禁用 &#xff1a; systemctl disable firewalld 开机…

SAP 通过 OData Service 反查 CDS View 位置 视图「Workaround」

前言 使用场景&#xff1a;目前已知 OData Service 由 CDS View 发布&#xff0c;但是想要查看该 CDS 的具体内容 根据 OData Service 获取关键信息盲猜对应底表通过 SE11 反查引用位置 猜底表 目前已知 OData Service URL: http://xxx.xxx.com:xxxx/sap/opu/odata/sap/ZCD…

栉风沐雨砥砺行,春华秋实满庭芳——华秋电子2022年度大事记

岁序更替&#xff0c;春华秋实 转眼间&#xff0c;2022年已是过去 回首2022年&#xff0c;华秋肩负使命 持续为电子产业增效降本。 我们加大研发投入&#xff0c;提升全球交付保障能力&#xff1b; 我们以创新引领发展&#xff0c;以实干笃定前行&#xff1b; 以品质为基…

JetBrains 学生和教师认证教程

目录一、学生和教师授权申请方式二、申请网址三、激活JetBrains产品&#xff08;如PyCharm、IDEA&#xff09;一、学生和教师授权申请方式 详见官方教程&#xff1a; JetBrains 学生和教师授权申请方式 二、申请网址 学生和教师可以使用在学校注册的邮箱账号来申请。 新申请…

「EZEC-4」可乐(2种方法:差分+位运算 | 枚举+字典树)

「EZEC-4」可乐 洛谷&#xff1a;「EZEC-4」可乐 题目背景 很久以前&#xff0c;有一个 pigstd&#xff0c;非常迷恋美味的可乐。为了得到美味的可乐&#xff0c;他几乎用尽了所有的钱&#xff0c;他甚至对自己的 npy 也漠不关心其实是因为他没有npy&#xff0c;更不爱好看戏…

C语言实现烟花表白,内含源码!!

虽然现在看烟花有一定难度&#xff0c;但代码式烟花可以随时随地看&#xff01; 烟花的代码很多&#xff0c;实际上是可以用 Python、HTML5 等语言写烟花&#xff0c;但今天主要想和大家分享用C语言写的烟花代码&#xff0c;非常细致和实用。 同学们一定要亲自敲一遍&#xf…

机器视觉(八):图像特征提取

目录&#xff1a; 机器视觉&#xff08;一&#xff09;&#xff1a;概述 机器视觉&#xff08;二&#xff09;&#xff1a;机器视觉硬件技术 机器视觉&#xff08;三&#xff09;&#xff1a;摄像机标定技术 机器视觉&#xff08;四&#xff09;&#xff1a;空域图像增强 …

理解文件系统

之前的东西&#xff0c;全部是在内存中的。但是我们知道&#xff1a;不是所有的文件&#xff0c;都被打开了。大量的文件&#xff0c;就在磁盘上放着&#xff0c;什么都不做。这些文件非常多&#xff0c;杂&#xff0c;乱。而磁盘级别的文件管理&#xff0c;本质工作就能够快速…