- 聊一聊HashMap底层的数据结构及扩容机制 ?
- 数据结构
HashMap是一个双链集合,集合中的每个元素是以键值对的形式存在,HashMap的特点是无序,不重复,无索引
HashMap底层数据结构在JDK1.7之前是数组+链表,而在JDK1.8之后是数组+链表+红黑树
HashMap主要依赖于哈希表(数组)来存储,数组中的每个位置都可以存放一个键值对,数组的索引是通过键的哈希码经过哈希函数计算出来的,这样可以通过键快速定位到数组的某个位置。
在实际使用中,可能会遇到两个不同的键计算出相同的哈希值,这就是“哈希冲突”,HashMap通过使用链表来解决这个问题,当哈希冲突发生的时候,HsahMap会在冲突的位置,增加一个链表,新的元素会添加到链表的末尾,每个链表中的元素都包含了相同哈希值的键值对,所以在查找元素的时候,如果遇到哈希冲突,HashMap需要进行一次线性查找
而在JDK8之后,链表的长度超过默认的阈值8,总数据量大于64的时候。那么链表就会转换成红黑树。
-
扩容机制
Java7情况下的扩容
HashMap在初始化的时候,会有会有一个默认的初始容量(16),默认的加载因子(0.75),也就是说当HashMap的存储大小超过容量*加载因子,也就是12的时候,HashMap会进行扩容,新的容量是原来的两倍。
但是注意的是,发生扩容除了满足大小超过阈值外,还需要发生Hash碰撞,也就是说当没有发生hash碰撞的时候,理想情况下最后存满16个值,再存入第17个的时候才发生扩容现象
除此之外还要一种情况,前11个值全部发生hash碰撞,全部存取到数组的同一个地方,再次存入第12个元素不会发生扩容,此时12个元素全部在同一个链表中,数组剩余15个位置是空的,后面存入的15个值全部分散到数组剩下的15个位置。所以12+15=27,在存入第28个值的时候才会发生扩容
Java8情况下的扩容
Java8中扩容只需要满足一个条件,Java8只需要满足一个条件,当前存放值的时候,已有的元素个数大于等于阈值,下一次存放必定触发扩容
(先存放后扩容)
2.请描述一下如何创建一个线程池,线程池的7个参数分别是什么意思?
corePoolSize:线程池核心线程大小
maximumPoolSize:线程池最大线程数量
keepAliveTime:空闲线程存活时间
unit:空闲线程存活时间单位
workQueue:工作队列
threadFactory:线程工厂
handler:拒绝策略
标签:扩容,Java,HashMap,小练,数组,链表,面试,线程,哈希 From: https://www.cnblogs.com/yifan0820/p/17859865.html