Map的前世今生

本文详细介绍了HashMap的扩容机制,包括默认扩容因子0.75和初始长度16的原因。讨论了链表转红黑树的阈值以及为何选择8和6。同时,文章指出HashMap的线程不安全问题,如并发扩容导致的环形链和数据丢失。最后,通过经典问题解析了HashMap在不同情况下的扩容行为。
摘要由CSDN通过智能技术生成

目录

目录

Map

扩容机制

HashMap默认使用扩容因子0.75.

HashMap的初始数组的长度为16.

链表转化为红黑树链表长度超过8,当数据元素小于6时恢复链表

线程不安全

put数据流程

java8

java7

经典题: 

准备用HashMap存1w条数据,构造时传10000还会触发扩容吗?

准备用HashMap存1000条数据,还可以用1000初始化吗?

1.8中做了哪些优化优化?


 

Map

已经被社会教育了千万遍,将HashMap的整体进行回顾与学习,有问题的请私信指教,共同学习与成长。以下将会进行简称HashMap(HM)

可以简单的将其看成是一个容器,存储的数据不是简单的String或者Integer,是有一点结构的数据。Java7中是Entry<K,V>,Java8中是Node<K,V>结构。

容器的作用就是对数据进行存储,存储就会有容量的概念,固定长度或者动态变化(根据数据内容),

 

case:

1、两个非常常用的不可变长度的集合:Collections.singletonList 和 Arrays.asList.

2、ArrayList 则是根据阈值动态扩容

扩容机制

  • HashMap默认使用扩容因子0.75.

(扩容因子的含义类似于数组数据饱满度,数组长度为10,则达到0.75的饱满度即存储8个数据时会触发自动扩容)。

扩容原理时:创建新的数组,将原数组的数据放到新的数组上。扩容成功后,数组长度是原来的2倍。

很多人会疑惑为什么使用0.75?

case:

使用1时,数据的出现hash冲突是很大的,这样会造成产生的红黑树就比较复杂,在进行数据查询时,效率降低。(时间浪费)

使用0.5时,数据出现hash冲突的机会是降低了,链表及红黑树相对简单,数据查询效率提升。但是数据只填充了一半就触发了扩容,对数据的内存造成了浪费。(空间浪费)

对于时间与空间进行折中处理,使用0.75 。

  • HashMap的初始数组的长度为16.

(2的n次幂) 分配过小防止频繁扩容,分配过大浪费资源。

//HashMap 进行put操作时,需要计算数据的下标。计算方法如下
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

由于和(length-1)运算,length 绝大多数情况小于2的16次方。所以始终是hashcode 的低16位(甚至更低)参与运算。要是高16位也参与运算,会让得到的下标更加散列(降低hash冲突)。因为&和|都会使得结果偏向0或者1 ,并不是均匀的概念,所以用^。

  • 链表转化为红黑树链表长度超过8,当数据元素小于6时恢复链表

链表长度超过8,另一次含义就是发生了8次的hash冲突(hash冲突时,才会存储到链表上)。【链表长度达到8个元素的概率为0.00000006,几乎是不可能事件,再变大没啥意义。】

红黑树退化为链表阈值为6?

中间有个差值7可以防止链表和树之间频繁的转换。若设置为小于8进行链表、红黑树转化。如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低。

线程不安全

HashMap的线程不安全主要体现在下面两个方面: 不安全
1.在JDK1.7中,当并发执行扩容操作时会造成环形链和数据丢失的情况。【rehash操作】
2.在JDK1.8中,在并发执行put操作时会发生数据覆盖的情况。

 

put数据流程

java8

java7

经典题: 

准备用HashMap存1w条数据,构造时传10000还会触发扩容吗?

// 预计存入 1w 条数据,初始化赋值 10000,避免 resize。
HashMap<String,String> map = new HashMap<>(10000)
// for (int i = 0; i < 10000; i++)

解析:

HashMap中有个非常巧妙的设计,初始化的时候有个tableSizeFor()方法,其

作用:(不考虑大于最大容量的情况)是返回大于输入参数且最近的2的整数次幂的数。比如10,则返回16。

目的:HashMap内部的数组大小强制为2的幂次方,这样在根据key的hash值通过按位与非常效率的找到key在数组中的位置。

   static final int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

固题目中的初始化为10000时进行tableSizeFor处理之后是 2 的 14 次幂 16384,默认扩容因子0.75,则达到16384*0.75 = 12288时才会触发扩容,很明显10000<12288,所以不会触发扩容操作。

准备用HashMap存1000条数据,还可以用1000初始化吗?

根据上面的分析,1000经过tableSizeFor处理之后是 2的10次幂 1024,再经过扩容因子0.75后是,1024*0.75 = 768 ,很明显 768< 1000, 此时便会触发扩容操作。

是否需要扩容分两步走:

1、tableSizeFor() 处理之后的结果(2的次幂)

2、扩容因子的阈值限定

1.8中做了哪些优化优化?

https://www.bilibili.com/read/cv6114752/

  • 数组+链表改成了数组+链表或红黑树
  • 链表的插入方式从头插法改成了尾插法
  • 扩容的时候1.7需要对原数组中的元素进行重新hash定位在新数组的位置,1.8采用更简单的判断逻辑,位置不变或索引+旧容量大小;
  • 在插入时,1.7先判断是否需要扩容,再插入,1.8先进行插入,插入完成再判断是否需要扩容;

 

 

 

 

 

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值