0


Map集合(超详解)

特点:

1.无序,键值对,键不能重复,值可以重复,这里的无序指的也是插入的顺序和读取的顺序是不一样的,和set集合一样。

  1. 键重复则覆盖,没有继承Collection接口,它单独继承Map接口,和list,set不一样,这两个继承collection接口

扩容:

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

遍历:

先获取所有键的Set集合,再遍历(通过键获取值)取出保存所有Entry的Set,再遍历此Set即可。

map的实现类

HashMap

  1. 线程不安全,最常用,速度快

  2. 内部采用数组来存放数据

put的执行过程

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

Table数组中的的Node

jdk1.8之前的链表结构示意图

jdk1.8 后的红黑树示意图

在这里,不得不说一下,什么是红黑树

特性:

  1. 每个节点要么红要么黑
  2. 根节点是黑色
    3 .每个叶子节点都是黑色(叶子是NULL节点表示 或 NIL节点表示)。
  3. 如果一个节点是红色的,那么它的子节点必须是黑色的子节点。(即不存在两个连续的红色节点)
  4. 从任一节点到其每个叶子结点(NULL节点或 NIL节点)的所有简单路径都包含相同数目的黑色节点。

红黑树其实就是以第一个数据作为判断依据,后面进来的数据与其做比较,比他小的就在这个数的左边,比这个数大的就在右边,然后继续往下走,接在下面一步一步往下走,这就是红黑树。

这里提供一个可视化红黑树网址

点我跳转红黑树https://www.cs.usfca.edu/~galles/visualization/RedBlack.html说完红黑树,我们来说一下jdk1.8之前的hashmap的原理怎么样的

首先在hashmap的底层有一个叫桶的数组,默认长度为16,这数组并不是保存的我们进来的元素,而是保存一个指向数据节点的一个指针,引用,首先通过key值hash运算,得到hashcould值,然后确定在数组上的位置,然后数据进来一个一个往下面的链表挤,往下挤,无论你有多少的元素我都一直往下挤。

而在jdk1.8后,先进行一个判断,判断你的元素长度是否大于8,如果小于8是一个链表结构,如果大于8是一个红黑树的结构,红黑树结构上面已经说了,所以这就是jdk1.8之后的一个区别,这样的结构使得map的速度更快了。

HashTable

线程安全,不太常用,与vector类似,将所有数据加一把锁,性能很高

ConcurrentHashMap

线程安全,比HashTable性能高,jdk1.8之前采用16把分段锁,将数据加锁,jdk1.8之后是每一个在数组的桶加锁,每一个桶一把锁,有多少桶就加多少锁,中间在赋值的时候才用的是cas,比较并替换。

TreeMap

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

LinkedHashMap

继承HashMap

LinkedHashMap是有序的,且默认为插入顺序

当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了

代码实现

 Map<String, String> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("name1", "josan1");
        linkedHashMap.put("name2", "josan2");
        linkedHashMap.put("name3", "josan3");
        Set<Entry<String, String>> set = linkedHashMap.entrySet();
        Iterator<Entry<String, String>> iterator = set.iterator();
        while(iterator.hasNext()) {
            Entry entry = iterator.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            System.out.println("key:" + key + ",value:" + value);
        }

案例代码,上面的具体代码

package com.zking.test;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.junit.Before;
import org.junit.Test;

public class Maptest {

    private Map<String, String> map = new HashMap<>();

    @Before
    public void setup() {
        map.put("1", "李凝");
        map.put("2", "张山");
        map.put("3", "吴飞");
        map.put("4", "徐民");
    }

    @Test
    public void demo1() {
        System.out.println(map.get("3"));
    }

    @Test
    public void demo() {
        map.put("5", "zs");
        System.out.println(map.get("1"));
        System.out.println(map.get("5"));
    }

    @Test
    public void demo2() {
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            System.out.println(map.get(key));
        }
//        获取value值
    }

    @Test
    public void demo9() {
        Iterator<Entry<String, String>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, String> entry = it.next();
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
//    获取key+value值
    }

    @Test
    public void demo10() {
        map.forEach((key, val) -> System.out.println(key + ":" + val));
//        foreach遍历出key+value值
    }

    @Test
    public void demo11() {
        if (!map.containsKey("4")) {
            map.put("4", "徐民");
        }
        map.putIfAbsent("4", "白牙");
//        map.putIfAbsent()如果这元素存在就不覆盖,put如果存在就覆盖
//        使用 put 方法添加键值对,如果 map 集合中没有该 key 对应的值,则直接添加,
//        并返回 value;如果已经存在对应的值,则会覆盖旧值,value 为新的值,返回值为 value。
//
//        2.使用 putIfAbsent 方法添加键值对,如果 map 集合中没有该 key 对应的值,则直接添加,
//        并返回 null,如果已经存在对应的值,则依旧为原来的值,返回值为 value(旧的值)。
        map.forEach((key, val) -> System.out.println(key + ":" + val));
    }

    @Test
    public void demo3() {
        Map<String, String> map = new HashMap<>();
        map.put("1", "李凝");
        map.put("2", "张山");
        map.put("3", "吴飞");
        map.put("4", "徐民");

        Iterator<Entry<String, String>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, String> next = it.next();
            System.out.println(next.getKey() + " : " + next.getValue());
        }
//        迭代器遍历出元素
    }

    @Test
    public void demo4() {
        // 对已存在的key为1的记录进行了覆盖
        map.put("1", "微信");
        System.out.println(map.get("1"));
    }

    @Test
    public void demo5() {

        // 如果指定的key值不存在,则加入map
        if (!map.containsKey("2")) {
            map.put("2", "rest");
        }

        // 更简单的方式
        String val = map.putIfAbsent("2", "rest");

        System.out.println(map.get("2"));
        System.out.println(val);
    }

    @Test
    public void demo6() {
        map.remove("1");

        map.forEach((key, val) -> System.out.println(key + ":" + val));
//删除方法        
    }

    @Test
    public void demo12() {
        Hashtable<String, String> table = new Hashtable();
        table.put("1", "指针");
        table.forEach((key, val) -> System.out.println(key + ": " + val));
//        Hashtable
    }

    @Test
    public void demo13() {
        ConcurrentHashMap<String, String> table = new ConcurrentHashMap<>();
        table.put("1", "指针");
        table.forEach((key, val) -> System.out.println(key + ": " + val));
    }
//    ConcurrentHashMap

}
private TreeMap<String,Student> treeMap;
    
    @Before
    public void setup() {
        treeMap = new TreeMap<String,Student>(new Comparator<String>() {

            @Override
            public int compare(String o1, String o2) {
                // TODO Auto-generated method stub
                // 负数   0  正数
                return o1.compareTo(o2);
            }

        });
        treeMap.put("1", new Student(1, "zs", 0));
        treeMap.put("2", new Student(3, "ls", 0));
        treeMap.put("3", new Student(2, "ww", 0));
        treeMap.put("4", new Student(4, "zl", 0));
    }
    
    @Test
    public void demo1() {
        treeMap.forEach((key, val) -> System.out.println(key + ":" + val));
    }
    
标签: 大数据 java

本文转载自: https://blog.csdn.net/weixin_67150631/article/details/125511020
版权归原作者 赤诚& 所有, 如有侵权,请联系我们删除。

“Map集合(超详解)”的评论:

还没有评论