11_6、Java集合之Map接口的使用

news2024/11/24 17:48:13

一、引入

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/144172.html

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

相关文章

在rhel6系统部署iscsi远程存储

文章目录一 需求二 环境准备三 服务端配置3.1 添加硬盘3.2 安装软件3.3 编写配置文件3.4 启动服务3.5 检查配置信息四 客户端配置4.1 安装软件包4.2 启动服务4.3 发现目标4.4 登陆目标4.5 实现开机自动挂载五 对部署进行测试一 需求 1&#xff09;首先在服务端添加一块10G的硬…

实验二十二 配置访问控制列表AGL

实验二十二 配置访问控制列表AGL一、 ACL基础概念 1、访问控制列表根据源地址、目标地址、源端口或目标端口等协议信息对数据包进行过滤&#xff0c; 从而达到访问控制的目的 。可以在路由器、三层交换机等设备上使用 &#xff0c;目前部分新二层交换 机也支持ACL。 2、ACL由编…

十、k8s DashBoard

文章目录1 部署Dashboard2 使用DashBoard之前在kubernetes中完成的所有操作都是通过命令行工具kubectl完成的。其实&#xff0c;为了提供更丰富的用户体验&#xff0c;kubernetes还开发了一个基于web的用户界面&#xff08;Dashboard&#xff09;。用户可以使用Dashboard部署容…

超级浏览器的技术原理,超级浏览器的浏览器指纹是什么?

浏览器指纹是超级浏览器的识别信息&#xff0c;网站可以通过这些信息来识别用户&#xff0c;判断用户的唯一性。常见的浏览器指纹有IP地址、浏览器所在地区、时区&#xff1b;用户代理&#xff08;User Agent&#xff09;相关的操作系统及版本、CPU 类型、浏览器及版本、浏览器…

吴恩达《机器学习》——PCA降维

PCA降维1. 主成分分析1.1 数据降维动机1.2 PCA降维目标问题分析2. PCA数学原理分析2.1 求协方差矩阵的碎碎念2.2 PCA实现方法3. Python实现3.1 进行人脸数据压缩数据集、源文件可以在Github项目中获得 链接: https://github.com/Raymond-Yang-2001/AndrewNg-Machine-Learing-Ho…

一些实用的办公工具分享给你

ABBYY FineReader 这是一个可以转换PDF格式的图片文字识别软件&#xff0c;下载之后可以免费试用七天&#xff0c;或者选择去它的网站上传PDF进行识别转换&#xff0c;一天最多可以转换10次&#xff0c;且一次只能转换3个页面。 【操作方法】 打开软件&#xff0c;点击“图像…

(day3)自学Java——面向对象

非原创&#xff0c;为方便自己后期复习 目录 1.类和对象 2.封装 3.就近原则和this关键字 4.构造方法 5.标准的javabean类 6.三种情况的对象内存图 7.基本数据类型和引用数据类型 8.this的内存原理 9.面向对象综合训练 (1)文字版格斗游戏 (2)两个对象数组练习 (3)对…

产品上新|语音识别+主题抽取,Magic Data多人会议数据集助您打造领先智能会议系统

2020年以来&#xff0c;新冠加快了线下向线上搬迁的速度&#xff0c;使得线上办公、在线教育、远程会议得到飞速普及和发展。艾媒咨询数据显示&#xff0c;2021年中国视频会议行业市场规模达148.2亿元。各类视频会议产品价格较低、操作便捷高效&#xff0c;普及率越来越高&…

vsftp开启登录,上传,下载,删除等操作审计日志

vsftp开启登录&#xff0c;上传&#xff0c;下载&#xff0c;删除等操作审计日志 背景 今天业务告知说有人把前天下午和昨天一天的ftp上面的附件被人删除了&#xff0c;首先我是非常的惊讶&#xff0c;居然会发生这种事&#xff0c;但是好在这个ftp不是我们负责的&#xff0c;…

驱动之设备模型

1. 起源与新方案 1.1 起源 仅devfs&#xff0c;导致开发不方便以及一些功能难以支持 热插拔不支持一些针对所有设备的同意操作&#xff08;如电源管理&#xff09;不能自动mknod用户查看不了设备信息设备信息硬编码&#xff0c;导致驱动代码通用性差&#xff0c;即没有分离设…

终章:学习路线

说明 该文章来源于徒弟lu2ker转载至此处&#xff0c;更多文章可参考&#xff1a;https://github.com/lu2ker/ 文章目录说明一些废话成果路线第一阶段要点第二阶段要点第三阶段要点第四阶段要点最后一些废话 截至这篇文章前已经有150star了&#xff0c;虽然比不上大佬们K级的量…

【链表】leetcode203.移除链表元素(C/C++/Java/Js)

leetcode203.移除链表元素1 题目2 思路 (两种方式&#xff09;2.1 在原来链表上进行删除2.2 设置一个虚拟头结点删除3 代码3.1 C &#xff08;两种方式&#xff09;3.2 C版本&#xff08;两种方式&#xff09;3.3 Java版本&#xff08;两种方式&#xff09;3.4 JavaScript版本4…

Vue的组件、组件的创建、data、methods

一、组件 组件是vue的重要的特征之一&#xff0c;可以扩展html的功能&#xff0c;也可以封装代码实现重复使用。 二、组件的创建 1. 非脚手架方式下创建 ​ 第一步&#xff1a;使用Vue.extend创建组件 ​ 第二步&#xff1a;使用Vue.component注册组件 ​ …

OpenGov(三):新波卡治理机制有哪些可期待?

OpenGov维持波卡开创的信念投票&#xff0c;与以前相同的方式进行&#xff0c;使用WebAssembly和几个链上投票机制。也就是说&#xff0c;OpenGov通过降低障碍&#xff0c;来更好地管理网络的日常决策&#xff0c;将流程推向去中心化。真正的重点是使提案的范围与通过治理流程的…

企业数字化转型到底是什么?

企业的数字化转型单单是从基础设施上变更&#xff0c;更要从企业数据从文化上入手&#xff0c;培养企业的数据文化&#xff0c;以数据驱动来促进业务发展。大家都把数据基础设施讲的很详细了&#xff0c;那么我就从企业的数据化转型当中的数据文化是什么&#xff1f;以下来为大…

Python类型注解(十)

python学习之旅(十) &#x1f44d;查看更多可以关注查看首页或点击下方专栏目录 一.为什么需要类型注解 在代码中提供数据类型的注解&#xff08;显式的说明&#xff09;&#xff0c;使用时能获得相关提示 帮助第三方IDE工具&#xff08;如PyCharm&#xff09;对代码进行类型推…

想从事网络信息安全的工作,该如何自学?

前言 【一一帮助网络安全入门和提升学习点这里一一】 由于我之前写了不少网络安全技术相关的文章&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人私信问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#…

第56篇-利用jsRpc获取某博的登录参数

声明:该专栏涉及的所有案例均为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系本人删帖! 文章目录 一、前言二、JsRpc的基本使用1.准备工作2.简单使用三、使用jsRpc获取微博登录参数1.网站分析2.构建rpc一、前言 以前使用…

记录 一次 小米路由器4C 刷openwrt 过程

前言 起因是4C的性能不太行&#xff0c;用久了网络也不稳定&#xff0c;且100M带宽跑不满&#xff0c;然后就换了路由器&#xff0c;闲置的这个准备哪来跑个Linux挂个bot来着&#xff0c;结果可好&#xff0c;刷完发现内存小的可怜呀&#xff0c;架构也不是主流的&#xff08;…

低代码助力工业软件发展,提升智能制造“软”实力

在《“十四五”智能制造发展规划》中&#xff0c;将工业软件作为加强自主供给的一个重点任务进行单独部署&#xff0c;强调了工业软件的工业属性&#xff0c;明确了工业软件对于智能制造的核心支撑作用&#xff0c;凸显了我国补足工业软件短板、以工业软件助推智能制造发展的决…