44、Map

news2025/7/7 21:10:53

一、基本介绍:

1、Map接口实现类的特点[很实用]

注意:这里讲的是JDK8的Map接口特点

1)Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value

2)Map 中的 key和value 可以是任何引用类型的数据,会封装到HashMap$Node 对象中

3) Map 中的 key 不允许重复,原因和HashSet 一样,如果有重复的,后面的key的value会把前面的相同的key的value替换掉

4) Map 中的 value 可以重复

5) Map 的key 可以为 null,value 也可以为null ,注意 key 为null, 只能有一个, value 为null,可以多个.

6)常用String类作为Map的 key,即key不一定得是String

7)key和value之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value,使用get()方法

package Collection_;

import java.util.HashMap;
import java.util.Map;

@SuppressWarnings({"all"})
public class Map_ {
    public static void main(String[] args) {
        Map map=new HashMap();
        map.put("no1","韩顺平");
        map.put("no2","张无忌");

        map.put("no1","张三丰");//当有相同的k,就等价于替换
        map.put("no3","张三丰");

        map.put(null,null);
        map.put(null,"abc");//替换上面的null

        map.put("no4",null);
        map.put("no5",null);

        map.put(1,"赵敏");
        map.put(new Object(),"金毛狮王");

        //通过get()方法,传入key,会返回对应的value
        System.out.println(map.get("no2"));
        System.out.println("map="+map);
    }
}
//张无忌
//map={no2=张无忌, null=abc, no1=张三丰, 1=赵敏, no4=null, no3=张三丰, no5=null, java.lang.Object@7ef20235=金毛狮王}
//输出的顺序与hash值有关,所以是无序的

2、Map接口的特点:(看源码)

(1)Map存放数据,一对k-v是放在一个HashMap$Node中的,有因为Node实现了Entry接口,有些书上也说,一对k-v就是一个Entry

3、Map接口的常用方法

 

 4、Map接口的遍历方法:

二、HashMap 

package Collection_;

import java.util.*;

@SuppressWarnings({"all"})
public class MapFor {
    public static void main(String[] args) {
        Map map=new HashMap();
        map.put("邓超","孙俪");
        map.put("王宝强","马蓉");
        map.put("宋喆","马蓉");
        map.put("刘令博",null);
        map.put(null,"刘亦菲");
        map.put("鹿晗","关晓彤");

        //第一组:先取出所有的Key,通过Key取出对应的Value
        Set keyset=map.keySet();
        //(1)增强for
        System.out.println("------------1.1增强for----------");
        for (Object key :keyset) {
            System.out.println(key+"-"+map.get(key));
        }
        //(2)迭代器
        System.out.println("------------1.2迭代器----------");
        Iterator iterator=keyset.iterator();
        while (iterator.hasNext()) {
            Object key =  iterator.next();
            System.out.println(key+"-"+map.get(key));
        }

        //第二组:把所有的values取出
        Collection values=map.values();
        //这里可以使用所有的Collections使用的遍历方法
        //(1)增强for
        System.out.println("------------2.1增强for----------");
        for (Object value :values) {
            System.out.println(value);
        }
        //(2)迭代器
        System.out.println("------------2.2迭代器----------");
        Iterator iterator1=values.iterator();
        while (iterator1.hasNext()) {
            Object value =  iterator1.next();
            System.out.println(value);
        }

        //第三组:EntrySet
        Set entrySet=map.entrySet();
        System.out.println("------------3.1增强for----------");
        for (Object entry :entrySet) {
            Map.Entry m=(Map.Entry)entry;//将entry向下转型成Map.Entry
            System.out.println(m.getKey()+"-"+m.getValue());
        }
        System.out.println("------------3.2迭代器----------");
        Iterator iterator2=entrySet.iterator();
        while (iterator2.hasNext()) {
            Object entry =  iterator2.next();
            //System.out.println(next.getClass());//HashMap$Node-->实现-->Map.Entry(getKey,getValue);
            Map.Entry m=(Map.Entry) entry;//向下转型成Map.Entry
            System.out.println(m.getKey()+"-"+m.getValue());
        }
    }
}
//------------1.1增强for----------
//邓超-孙俪
//宋喆-马蓉
//刘令博-null
//null-刘亦菲
//王宝强-马蓉
//鹿晗-关晓彤
//------------1.2迭代器----------
//邓超-孙俪
//宋喆-马蓉
//刘令博-null
//null-刘亦菲
//王宝强-马蓉
//鹿晗-关晓彤
//------------2.1增强for----------
//孙俪
//马蓉
//null
//刘亦菲
//马蓉
//关晓彤
//------------2.2迭代器----------
//孙俪
//马蓉
//null
//刘亦菲
//马蓉
//关晓彤
//------------3.1增强for----------
//邓超-孙俪
//宋喆-马蓉
//刘令博-null
//null-刘亦菲
//王宝强-马蓉
//鹿晗-关晓彤
//------------3.2迭代器----------
//邓超-孙俪
//宋喆-马蓉
//刘令博-null
//null-刘亦菲
//王宝强-马蓉
//鹿晗-关晓彤

1、练习题:

 //我的代码:

package Collection_;

import java.util.*;

@SuppressWarnings({"all"})
public class MapExercise {
    public static void main(String[] args) {
        Map map=new HashMap();
        map.put(1234,new Employee("jack",10000,"1234"));
        map.put(1235,new Employee("tom",20000,"1235"));
        map.put(1236,new Employee("smith",30000,"1236"));
        System.out.println("========第一种遍历方式========");
        Set keyset=map.keySet();
        System.out.println("========增强for循环========");
        for (Object key :keyset) {
            Employee employee=(Employee) map.get(key);
            if(employee.getSal()>18000) {
                System.out.println(employee);
            }
        }
        System.out.println("========迭代器========");
        Iterator iterator=keyset.iterator();
        while (iterator.hasNext()) {
            Object key =  iterator.next();
            Employee employee=(Employee) map.get(key);
            if(employee.getSal()>18000) {
                System.out.println(employee);
            }
        }
        System.out.println("========第二种遍历方式========");
        Set entrySet=map.entrySet();
        System.out.println("========增强for循环========");
        for (Object entry :entrySet) {
            Map.Entry m=(Map.Entry) entry;
            Employee employee=(Employee) m.getValue();
            if(employee.getSal()>18000) {
                System.out.println(employee);
            }
        }
        System.out.println("========迭代器========");
        Iterator iterator1=entrySet.iterator();
        while (iterator1.hasNext()) {
            Object entry =  iterator1.next();
            Map.Entry m=(Map.Entry) entry;
            Employee employee=(Employee) m.getValue();
            if(employee.getSal()>18000) {
                System.out.println(employee);
            }
        }

    }
}
class Employee{
    private String name;
    private double sal;
    private String id;

    public Employee(String name, double sal, String id) {
        this.name = name;
        this.sal = sal;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSal() {
        return sal;
    }

    public void setSal(double sal) {
        this.sal = sal;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", sal=" + sal +
                ", id='" + id + '\'' +
                '}';
    }
}
//========第一种遍历方式========
//========增强for循环========
//Employee{name='tom', sal=20000.0, id='1235'}
//Employee{name='smith', sal=30000.0, id='1236'}
//========迭代器========
//Employee{name='tom', sal=20000.0, id='1235'}
//Employee{name='smith', sal=30000.0, id='1236'}
//========第二种遍历方式========
//========增强for循环========
//Employee{name='tom', sal=20000.0, id='1235'}
//Employee{name='smith', sal=30000.0, id='1236'}
//========迭代器========
//Employee{name='tom', sal=20000.0, id='1235'}
//Employee{name='smith', sal=30000.0, id='1236'}

2、HashMap小结:

1)Map接口的常用实现类:HashMap、Hashtable和Properties。

2)HashMap是Map 接口使用频率最高的实现类。

3)HashMap 是以 key-val 对的方式来存储数据(HashMap$Node类型)

4) key 不能重复,但是是值可以重复,允许使用null键和null值。

5)如果添加相同的key,则会覆盖原来的key—val,等同于修改.(key不会替换,val会替换)

6)与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.

7)HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized 

3、HashMap底层机制及源码剖析:

  (1)扩容机制[和HashSet相同]
1)HashMap底层维护了Node类型的数组table,默认为null
2)当创建对象时,将加载因子(loadfactor)初始化为0.75.
3)当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断元素的key是否和准备加入的key相等,如果相等,则直接替换val;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容
4)第1次添加,则需要扩容table容量为16,临界值(threshold)为12(16*0.75)
5)以后再扩容,则需要扩容table容量为原来的2倍,临界值为原来的2倍,即24,依次类推

6)在Java8中,如果一条链表的元素个数超过TREEIFYTHRESHOLD(默认是8),并且table的大小>=MINTREEIFYCAPACITY(默认64),就会进行树化(红黑树)

//解读源码:
package Collection_;

import java.util.Comparator;
import java.util.TreeMap;
@SuppressWarnings({"all"})
public class TreeMap_ {
    public static void main(String[] args) {
//        TreeMap treeMap=new TreeMap();
//        treeMap.put("dddjack","杰克");
//        treeMap.put("aaatom","汤姆");
//        treeMap.put("ccckristina","克瑞斯提诺");
//        treeMap.put("bbbsmith","史密斯");
//
//        System.out.println("treemap="+treeMap);
          //输出:treemap={aaatom=汤姆, bbbsmith=史密斯, ccckristina=克瑞斯提诺, dddjack=杰克}
          //使用默认构造器,则是按首字母前后排序

        TreeMap treeMap=new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                //按照传入的k(String)的大小进行排序
                return ((String)o1).compareTo((String)o2);//从小到大

                //return ((String)o2).compareTo((String)o1);
                //从大到小
                //输出:treemap={dddjack=杰克, ccckristina=克瑞斯提诺, bbbsmith=史密斯, aaatom=汤姆}

                //return ((String)o1).length()-((String)o2).length();
                //按照传入的k(String)的长度大小进行排序
                //输出:treemap={aaatom=汤姆, dddjack=杰克, bbbsmith=史密斯, ccckristina=克瑞斯提诺}
                //注意:如果要添加的key的长度和已有的某个key的长度一样,那这个key就添加不进去,
                //cmp = cpr.compare(key, t.key);
    //                else {
    //                    V oldValue = t.value;
    //                    if (replaceOld || oldValue == null) {
    //                        t.value = value;
    //                    }
    //                    return oldValue;
    //                }
                //但是它的值会替换已有的那个key的值
            }
        });
        treeMap.put("dddjack","杰克");
        treeMap.put("aaatom","汤姆");
        treeMap.put("ccckristina","克瑞斯提诺");
        treeMap.put("bbbsmith","史密斯");
        System.out.println("treemap="+treeMap);
        //输出:treemap={aaatom=汤姆, bbbsmith=史密斯, ccckristina=克瑞斯提诺, dddjack=杰克}
        //跟使用默认情况时一样,说明默认情况下的底层机制即为这个
    }
}
/*
源码剖析:
    //1、构造器,把传入的实现了Comparator接口的匿名内部(对象),传给TreeMap的comparator
    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }
    //2、调用put方法
    //2.1 第一次添加,把k-v封装到Entry对象,放入root
    Entry<K,V> t = root;
        if (t == null) {
            addEntryToEmptyMap(key, value);
            return null;
        }
    //2.2
    Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            do {//遍历所有的key,给当前的key找到适当的位置,
                parent = t;
                cmp = cpr.compare(key, t.key);//动态绑定到我们的匿名内部类的compare()方法
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else {//如果遍历过程中,发现准备添加的key和当前已有的key相等,就不添加了
                    V oldValue = t.value;
                    if (replaceOld || oldValue == null) {
                        t.value = value;
                    }
                    return oldValue;
                }
            } while (t != null);
        }
 */

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

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

相关文章

5个超好用的视频素材网站,视频剪辑必备。

推荐五个高质量视频素材网站&#xff0c;免费、可商用&#xff0c;赶紧收藏起来&#xff01;1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx网站素材非常丰富&#xff0c;有平面、UI、电商、办公、视频、音频等相关素材&#xff0c;视频素材质量很高&#xff0c;…

SpringBoot2.x系列教程31--SpringBoot中的缓存实现方案介绍

前言 作为一个程序员&#xff0c;我们不仅仅要把项目的功能实现出来&#xff0c;还要追求这个功能的高效和健壮&#xff0c;我们得想办法对项目的功能进行各种优化和性能的提升。其中缓存就是对程序性能进行显著提升的一个有效手段&#xff0c;那么在SpringBoot中对缓存有哪些…

我的数学学习回忆录——一个数学爱好者的反思(一)

早点关注我&#xff0c;精彩不迷路&#xff01;我是一个热爱数学20余年的数学爱好者&#xff0c;曾奉数学为宇宙的真理和一切行动的指南的极客。从小对数字世界好奇和敏感&#xff0c;玩各种数学思维游戏&#xff0c;然后在高考应试和竞赛中扎实训练数学基础&#xff0c;逐渐把…

[附源码]java毕业设计中华美食网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

docker安装filebeat 进行日志收集

1.介绍 filebeat和beats的关系 首先filebeat是Beats中的一员。   Beats在是一个轻量级日志采集器&#xff0c;其实Beats家族有6个成员&#xff0c;早期的ELK架构中使用Logstash收集、解析日志&#xff0c;但是Logstash对内存、cpu、io等资源消耗比较高。相比Logstash&#x…

matlab学习笔记(五)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 matlab学习笔记&#xff08;五&#xff09;一、绘制下列连续时间信号的波形图二、绘制下列离散时间信号的波形图三.已知信号f(t)的波形如下图所示&#xff0c;请用MATLAB绘出…

ES filter查询 高亮查询 聚合查询

filter查询 query&#xff0c;根据你的查询条件&#xff0c;去计算文档的匹配度得到一个分数&#xff0c;并且根据分数进行排序&#xff0c;不会做缓存的。 filter&#xff0c;根据你的查询条件去查询文档&#xff0c;不去计算分数&#xff0c;而且filter会对经常被过滤的数据进…

C++中的多态(上)

&#x1f9f8;&#x1f9f8;&#x1f9f8;各位大佬大家好&#xff0c;我是猪皮兄弟&#x1f9f8;&#x1f9f8;&#x1f9f8; 文章目录一、多态的概念二、虚函数三、破坏多态条件的现象1.破坏多态条件一&#xff0c;虚函数重写/覆盖2.破坏多态条件二四、 多态的两个条件不满足…

数据库审核工具SQLE部署及使用

点击上方蓝字关注我SQLE&#xff08; https://opensource.actionsky.com/sqle/ &#xff09;是由上海爱可生信息技术股份有限公司 开发并开源&#xff0c;支持多场景审核&#xff0c;支持标准化上线流程&#xff0c;原生支持 MySQL 审核且数据库类型可扩展的 SQL 审核工具。我们…

PC_磁盘HDD_SSD

文章目录磁盘存储器组成磁盘驱动器磁盘控制器盘片platter存储区域磁盘结构磁道track扇区sector&#x1f388;/块Block&#x1f386;磁头(Head)圆柱面cylinder磁记录原理磁盘性能指标记录密度磁盘的容量非格式化容量格式化容量数据传输率磁盘转速旋转周期T例平均存取时间纯读/写…

网络与通信程序设计-基于UDP的广播通信实例

目录 实验内容和设计思想 实验的内容 UDP的设计思想 UDP的协议头部 UDP通信编程思想 UDP的工作流程 UDP编程收发函数 广播通信 广播模式设置 广播套接字 UDP Socket的使用过程 UDP广播通信实例实现 initsock.h 服务器发送广播消息 客户端接收广播消息 运行效果 …

HttpMessageConverter 消息转换器

HttpMessageConverter 简介 HttpMessageConverter 是SpringMVC中提供的一个策略接口&#xff0c;它是一个消息转换器类&#xff0c;Spring Mvc中就是由HttpMessageConverter负责转换HTTP的请求和响应。 默认情况下&#xff0c;Spring Boot 会自动加载如下消息类型转换器&…

spring复习01,IOC的思想和第一个spring程序helloWorld

spring复习01&#xff0c;IOC的思想及本质IOC的思想一个小例子&#xff0c;来体会IOC的基础思想。dao层dao层接口dao层实现类service层service层接口service层实现类测试代码service层实现类修改测试代码修改IOC容器在spring中的简单实现创建项目在pom.xml中引入依赖实体类创建…

C# 拨号面板 高亮显示

一 拨号面板 显示&#xff1a;绘制4x3; 数据&#xff1a;每一格对应一个数字&#xff1b; 行为&#xff1a;点击单元格时有反应&#xff1b; 二 拨号事件 当点击某个号码时&#xff0c;触发拨号事件。 设计思路&#xff1a; ① 重写OnMouseClick(); ② 根据鼠标点击位置&am…

JVET-AB0117-基于模板的帧内推导的方向性融合

本提案是针对 ECM 中的 TIMD&#xff08;基于模板的帧内模式推导&#xff0c;Template based intra mode derivation &#xff09; 的技术的加权方式的改进。具体地&#xff0c;本提案提出使用方向混合&#xff08;directional blending&#xff09;来加权TIMD使用模板推导的两…

SpringBoot SpringBoot 原理篇 1 自动配置 1.13 bean 依赖属性配置

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 原理篇 文章目录SpringBootSpringBoot 原理篇1 自动配置1.13 bean 依赖属性配置1.13.1 环境准备1.13.2 bean 依赖属性配置1…

【软件测试】作为测试人,因工作与开发吵了一架碰撞,该咋办......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 测试与开发在工作中…

【网页设计】HTML+CSS保护野生动物北极熊介绍网页设计专题

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

傻白入门芯片设计,RDL/Interposer/EMIB/TSV(五)

一、再分配层&#xff08;RDL&#xff09; 主要原理就是在晶片表面沉积金属层和介电层。它形成了一个再分配层&#xff0c;以携带相应的金属布线模式&#xff0c;并在芯片外的松散区域上重新排列芯片的IO端口。由于RDL形成的金属布线的线宽和间距较小&#xff0c;从而提供了更…

MySQL之InnoDB架构浅析

InnoDB是一个兼顾高可靠性和高性能的通用存储引擎。在 MySQL 5.7 中&#xff0c;InnoDB是默认的 MySQL 存储引擎。 InnoDB 的主要优势 支持事物&#xff0c;具备crash-safe的能力支持行锁以及MVCC&#xff0c;具备良好的多用户并发性和性能Buffer Pool&#xff0c;提升热点数…