Java-Map从入门到性能分析2【HashMap的底层原理、构造方法优化、常用方法】

【视频网址】:慕课网——Map从入门到性能分析

简介:Map是开发中,使用频率最高的知识点之一,Map家族也有很多成员,例如HashMap,LinkedMap等, 怎样更好地使用Map家族的这些成员,速度效率怎么更好地得以发挥,我将自己的一些经验与大家分享。



工程文件【链接:https://pan.baidu.com/s/1Vg3FLVtGeCCKZ3R68Xi2tA【提取码:zjxs

目   录

第3章 HashMap的原理

3-1 HashMap例题2(15:58)

3-2 HashMap底层原理1(08.50)

3-3 HashMap底层原理2(06.14)

3-4 HashMap构造方法优化1(13:56)

3-5 HashMap构造方法优化2(12:02)

3-6 HashMap常用方法1(20:50)

3-7 HashMap常用方法2(07:21)


第3章 HashMap的原理

3-1 HashMap例题2(15:58)

Map中的value对象的形式进行存储

对象包含对象!

对于 小Map:key是三门课程,value是成绩(90、80、72)。

对于 大Map:key是zhang1,value是map1、map2、map3...

//加上泛型,只能存Map;不加泛型,存啥都行。一般都加泛型
//List list = new ArrayList();
//List<Map> list = new ArrayList<Map>();
List<Map<String, String>> list = new ArrayList<Map<String, String>>();

使用Map进行定位,更方便。

package com.imooc;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestMap1 {
    public static void main(String[] args) {
        Map<String, Map> stuMap = new HashMap<String, Map>();//<String, Object> Map也是Object

        Map<String, String> stu1Map = new HashMap<String, String>();
        stu1Map.put("1yuwen", "11");
        stu1Map.put("2shuxue", "12");
        stu1Map.put("3yingyu", "13");
        Map<String, String> stu2Map = new HashMap<String, String>();
        stu2Map.put("1yuwen", "21");
        stu2Map.put("2shuxue", "22");
        stu2Map.put("3yingyu", "23");
        Map<String, String> stu3Map = new HashMap<String, String>();
        stu3Map.put("1yuwen", "31");
        stu3Map.put("2shuxue", "32");
        stu3Map.put("3yingyu", "33");
        Map<String, String> stu4Map = new HashMap<String, String>();
        stu4Map.put("1yuwen", "41");
        stu4Map.put("2shuxue", "42");
        stu4Map.put("3yingyu", "43");
        Map<String, String> stu5Map = new HashMap<String, String>();
        stu5Map.put("1yuwen", "51");
        stu5Map.put("2shuxue", "52");
        stu5Map.put("3yingyu", "53");

        stuMap.put("zhang1", stu1Map);
        stuMap.put("zhang2", stu2Map);
        stuMap.put("zhang3", stu3Map);
        stuMap.put("zhang4", stu4Map);
        stuMap.put("zhang5", stu5Map);

        System.out.println(stuMap);
        System.out.println(stuMap.get("zhang3"));

        //加上泛型,只能存Map;不加泛型,存啥都行。一般都加泛型
        //List list = new ArrayList();
        //List<Map> list = new ArrayList<Map>();
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        list.add(stu1Map);
        list.add(stu2Map);
        list.add(stu3Map);
        list.add(stu4Map);
        list.add(stu5Map);
        System.out.println(list);
        System.out.println(list.get(2));
    }
}

3-2 HashMap底层原理1(08.50)

HashMap初始化大小,默认是长度为16的数组。

底层原理:取余数实现定位!底层代码:通过位运算取余数进行定位。

链表形式存储。entry中的next变量解决碰撞问题!【8的坐标指向120,120的键值映射中的next指向40,40的next指向null。】

取值:key转换成哈希码!!!

 

package com.imooc;

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

public class TestMap2 {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<Integer, String>();
        //map.put(120,"a");//120是int类型的,自动转成Integer
        map.put(new Integer(120), "a");
        map.put(new Integer(37), "a");
        map.put(new Integer(61), "a");
        map.put(new Integer(40), "a");
        map.put(new Integer(92), "a");
        map.put(new Integer(78), "a");
        System.out.println(map);
    }
}

3-3 HashMap底层原理2(06.14)

  1. 根据key得到优化后的哈希码;
  2. 根据优化后的哈希码,对长度取余,得到的余数就是位置。【底层通过位运算求余!】

有效使用空间:默认长度*负载因子。超出之后,进行扩容,默认扩容1倍。

Java开源团队多次实验的结果:16、0.75最佳!!!

3-4 HashMap构造方法优化1(13:56)

初始化大小。创建好的HashMap长度为3。
HashMap构造方法的优化:将传递的参数转化为“大于参数的最小的2^n”。【2^2-->4】

负载因子:占有率达到多少后,进行扩容,扩容1倍。

负载因子为1:0~15的位置,都要占满,才会扩容。数字求余,决定所处位置。

可能会在某个位置出现多次碰撞,始终达不到100%的占用,导致节点中产生空度映射关系。

链表达到一定量后,将其转换为 红黑树!!!

调整位置:运行时间、性能消耗。扩容次数,越少越好!-->考虑初始化大小!-->与业务匹配!

3-5 HashMap构造方法优化2(12:02)

第1次 运行时间较长,程序第1次执行的时候要进行内存的分配。【Java虚拟机做内存分配!】

package com.imooc;

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

/**
 * 1、创建10个HashMap,每个HashMap含有10万条记录;
 * 2、传递不同的构造方法的参数,比较速度;
 * 3、实验参数:构造方法传参(16, 0.75f)和(16384, 0.75).
 */
public class TestMap3 {
    public static void main(String[] args) {
        Long sum = 0L;
        for (int i = 0; i < 10; i++) {
            sum += new TestMap3().inputMap1(10000, 0.75f);
        }
        System.out.println(sum / 10);
    }

    private Long inputMap1(int initialCapacity, float loadFactor) {
        String key, value;
        Map<String, String> map1 = new HashMap<String, String>(initialCapacity, loadFactor);
        Long start = System.nanoTime();//计算时间、Long型变量   计数器---纳秒
        for (int i = 0; i < 10000; i++) {
            key = String.valueOf(i);
            value = "value";
            map1.put(key, value);
        }
        Long end = System.nanoTime();
        Long time = end - start;
        System.out.println("time:" + time);
        return time;
    }
    
}

3-6 HashMap常用方法1(20:50)

package com.imooc;

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

/**
 * 用的到技术点:
 * 1、putIfAbsent、put
 * 2、replace
 * 3、remove、cLear
 * 4、containsKey、containsValue
 * 5、isEmpty
 */
public class TestMap4 {
    public static void main(String[] args) {
        Map<String, String> map1 = new HashMap<String, String>();
        map1.put("a", "111");
        map1.put("b", "222");
        map1.put("c", "333");
        map1.put("d", "444");
        map1.put("e", "555");

        //1、判断是否为空
        boolean isNull = map1.isEmpty();
        System.out.println("map1 is Null: " + isNull);

        //2、删除节点
//        map1.remove("a1");
//        map1.remove("a","123");

        //3、清空HashMap对象
//        map1.clear();

        //4、判断是否有某个key
        boolean isFlag = map1.containsKey("a");
        System.out.println(isFlag);

        //5、判断是否有某个value
        boolean isFlag2 = map1.containsValue("555");

        //6、HashMap替换某个key的value
        map1.replace("a", "111111111");//key存在,就更新
        map1.replace("b", "2202", "22222");//key、value匹配,才更新
        map1.put("c", "33333");//key存在,则替换value;key不存在,则新增key
        System.out.println(map1);

        //7、putIfAbsent
        //避免代码量多,遗忘map中已存在的键值对,而进行替换
        if (map1.containsKey("c") && map1.containsValue("333")) {
            map1.put("c", "33333");
        }
        //避免代码量多,遗忘map中已存在的键值对,而进行替换【有效避免!!!】
        String x = map1.putIfAbsent("x", "8");//x存在,不执行put,输出x对应的值;x不存在,则put,输出null
        System.out.println(x);
    }
}

3-7 HashMap常用方法2(07:21)

package com.imooc;

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

/**
 * 1、map.forEach((key, value) -> System.out.println(key + ":" + value));
 * Lamaba表达式:->
 * 2、getOrDefault(key, defaultValue)
 */
public class TestMap5 {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(new Integer(11), "a");
        map.put(new Integer(22), "a");
        map.put(new Integer(33), "a");
        map.put(new Integer(44), "a");
        map.put(new Integer(55), "a");
        map.put(new Integer(66), "a");
        //1.1、1行表达式
        map.forEach((key, value) -> System.out.println(key + ":" + value));
        //1.2、多行表达式【需要用{}包裹!】
        map.forEach((key, value) -> {
            //System.out.println("---111---");
            System.out.print(key + ":" + value + "、");
            //System.out.println("---222---");
        });
        System.out.println();

        //2、key存在,输出key对应的value值;key不存在,输出默认值defaultValue
        System.out.println(map.getOrDefault("11", "***"));
        System.out.println(map.getOrDefault(new Integer(11), "***"));
        System.out.println(map.getOrDefault(new Integer(12), "***"));
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

upward337

谢谢老板~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值