• Map集合


    目录

    一、特点

    二、扩容

    三、遍历

    四、实现

    HashMap

    HashTable

    ConcurrentHashMap

    TreeMap

    LinkedHashMap


    一、特点

    无序,键值对,键不能重复,值可以重复,键重复则覆盖,没有继承Collection接口

    二、扩容

    扩容:初始容量16,负载因子0.75,扩容增量1倍

    三、遍历

    准备数据

    1. private Map<String, Object>map=new HashMap<String, Object>();
    2. @Before
    3. public void setup() {
    4. map.put("1", "鼠标");
    5. map.put("1", "电脑");
    6. map.put("2", "风扇");
    7. map.put("3", "书包");
    8. map.put("4", "演讲");
    9. map.putIfAbsent("1", "aaa");//如果缺失则加进去
    10. }

    🟡先获取所有键的Set集合,再遍历(通过键获取值)

    1. @Test
    2. public void test01() {
    3. Iterator<String>it=map.keySet().iterator();
    4. while(it.hasNext()) {
    5. String key = it.next();
    6. System.out.println(map.get(key));
    7. }
    8. }

    效果图如下: 

      

    🟡取出保存所有Entry的Set,再遍历此Set即可

    1. @Test
    2. public void test02() {
    3. Iterator<Entry<String, Object>> it = map.entrySet().iterator();
    4. while(it.hasNext()) {
    5. Entry e=it.next();
    6. System.out.println("key = "+ e.getKey() +" value ="+ e.getValue());
    7. }
    8. }

    效果图如下: 

     

    四、实现

    • HashMap

    HashMap的线程不安全,但是最为常用,速度快。内部采用数组来存放数据。

    首先来了解了解执行过程

    当我们往map里面put 元素时,会先检查这个数组是否存在。若没有存在,则会分配一个默认长度为16的数组。数组里面不是直接保存元素,而是经过一系列运算,通过给出的key获取到key在数组中的位置,这个数组称为桶(通过计算算出节点在几号桶里面)。图中桶指向的元素是Node节点(Node实际是Entry<k,v>)。每次添加元素时会经过计算,若没有元素,则会声明一个节点放进去,如果存放的元素是一样的则会被覆盖,反之,则会通过链表的方式往下增加(新增得元素在上方,原来的元素往下走)。 

     如何拿值?先经过计算,通过key找到元素所在的桶,若发现是一个链表,则进行链表遍历的方式找到元素。

    在元素多的情况下,上面的方法查找的时候需要全部遍历,存在缺点。运用二叉树的方式进行查找 ,通过元素的条件进行遍历,不需要那个链表都进行遍历。

     了解结构之后再来看看基本原理

    首先向Map里面put值,若发现为空,生成一个新的空,再根据key的hush值计算数组中对应的下标。如果数组里面没有值则生成一个新的节点,有值得话就生成节点进行判断,若大于8,转换为红黑树保存节点信息,不大于8就将信息保存到链表中。

     注意:流程图中绿色标出的部分为JDK8新增的处理逻辑,目的是在Table[i]中的Node节点数量大于8时,通过红黑树提升查找速度。

    • HashTable

    HashTable线程安全但是不为常用

    1. public void test03() {
    2. Map<Integer, Object>table=new Hashtable<Integer, Object>();
    3. table.put(1, "张三");
    4. table.put(2, "李四");
    5. table.put(3, "王五");
    6. table.put(4, "老刘");
    7. Iterator<Integer> it = table.keySet().iterator();
    8. while(it.hasNext()) {
    9. int key=it.next();
    10. System.out.println(table.get(key));
    11. }
    12. }
    • ConcurrentHashMap

    线程安全,比HashTable性能高

    1. public void test04() {
    2. Map<Integer, Object>cmap=new ConcurrentHashMap<Integer, Object>();
    3. cmap.put(1, "张三");
    4. cmap.put(2, "李四");
    5. cmap.put(3, "王五");
    6. cmap.put(4, "老刘");
    7. Iterator<Integer> it = cmap.keySet().iterator();
    8. while(it.hasNext()) {
    9. int key=it.next();
    10. System.out.println(cmap.get(key));
    11. }
    12. }
    • TreeMap

    key值按一定的顺序排序,添加或获取元素时性能较HashMap慢,是因为需求维护内部的红黑树,用于保证key值的顺序。

    1. public void test05() {
    2. Map<Integer, Object>tmap=new TreeMap<Integer, Object>();
    3. tmap.put(1, "张三");
    4. tmap.put(2, "李四");
    5. tmap.put(3, "王五");
    6. tmap.put(4, "老刘");
    7. Iterator<Integer> it = tmap.keySet().iterator();
    8. while(it.hasNext()) {
    9. int key=it.next();
    10. System.out.println(tmap.get(key));
    11. }
    12. }

     key值默认为升序,若想按照降序排序可以使用比较器(用key进行比较)

    1. public void test05() {
    2. Map<Integer, Object>tmap=new TreeMap<Integer, Object>(new Comparator<Integer>() {
    3. @Override
    4. public int compare(Integer o1, Integer o2) {
    5. return o2-o1;
    6. }
    7. });
    8. tmap.put(1, "张三");
    9. tmap.put(2, "李四");
    10. tmap.put(3, "王五");
    11. tmap.put(4, "老刘");
    12. Iterator<Integer> it = tmap.keySet().iterator();
    13. while(it.hasNext()) {
    14. int key=it.next();
    15. System.out.println(tmap.get(key));
    16. }
    17. }

    效果图如下:

    • LinkedHashMap

    继承HashMap,LinkedHashMap是有序的,且默认为插入顺序,当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了

    1. public void test06() {
    2. Map<String, String> linkedHashMap = new LinkedHashMap<>();
    3. linkedHashMap.put("name1", "josan1");
    4. linkedHashMap.put("name2", "josan2");
    5. linkedHashMap.put("name3", "josan3");
    6. Set<Entry<String, String>> set = linkedHashMap.entrySet();
    7. Iterator<Entry<String, String>> iterator = set.iterator();
    8. while(iterator.hasNext()) {
    9. Entry entry = iterator.next();
    10. String key = (String) entry.getKey();
    11. String value = (String) entry.getValue();
    12. System.out.println("key:" + key + ",value:" + value);
    13. }
    14. }

    效果如下:

     

  • 相关阅读:
    【python基础学习3】jupyter notebook 相关技巧学习
    轻量级项目任务管理工具DooTask
    Coremail城市沙龙活动|齐聚古城西安,护航信息安全
    Win通过WSL配置安装Redis
    51单片机数字电压表仿真设计_LCD显示(仿真+程序+原理图+PCB+设计报告+讲解)
    (C++)字符串相加
    koa实战 (一):项目搭建
    UrlBasedViewResolver类简介说明
    Go 语言特性与设计哲学
    C#60个常见的问题和答案
  • 原文地址:https://blog.csdn.net/weixin_62270300/article/details/125505809