余腾

导航

Map的结构理解

Map中的key:可以无序的、不可重复的,使用Set存储所有key ----->所在的类必须要重新equals()和hashCode()方法 因为key必须不可重复 (以HashMap为例)
Map中的value:无序的、可重复的,使用Collection存储所有value ------>value所在的类要重写equals()方法
一个键值对:key-value 构成了一个Entry对象。
Map中的Entry:无序的、不可重复的,使用Set存储所有的Entry

HashMap的底层实现原理?以jdk7为例说明:
HashMap map=new HashMap();
在实例化以后,底层创建了长度是16的一维数组,Entry【】 table.
..... 可能已经执行过多次put....
map.put(key1,value1):
首先,调用key1所在类的hashCode() 计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置
如果此位置的数据为空,此时key1-value1 添加成功-------->情况1
如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),比较key1和已经存在的一个或多个数据的哈希值:
如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。-------->情况2
如果key1的哈希值与已经存在的数据(key2-value2)的哈希值相同,那么此时继续比较:调用key1所在类的equals方法,比较:
如果equals() 返回false :key1-value1添加成功-------->情况3
如果equals() 返回true :key1-value1 使用value1替换key2的value值
补充:关于情况2和情况3:此时key1-value1 和原来的数据以链表的方式存储
在不断的添加过程中,会涉及到扩容问题,默认的扩容方式为原来容量的2倍,并将原来的数据复制过来。

JDK8 相比较于JDK7在底层实现方面的不同:
1 new HashMap(): 底层没有创建长度为16的数组
2 JDK8 底层的数组是:Node[],而非Entry[]
3 首次调用put()方法时,底层创建长度为16的数组
4 jdk7底层结构只有:数组+链表。jdk8中底层结构:数组+链表+红黑树
当数组的某个索引位置上元素以链表形式存在的数据个数>8 且当前数组的长度>64,此时索引位置上的所有数据改为红黑树存储(核心修改)为了遍历快,方便查找
当数组的某个索引位置上的元素以链表形式的存在的数据个数>8且当前数组的长度>64时,此时索引位置上的所有数据改为使用红黑树存储
DEFAULT_INITIAL_CAPACITY: HashMap的默认容量为16
DEFAULT_LOAD_FACTOR:HashMap的默认加载因子:0.75
threshold:扩容的临界值,=容量填充因子(160.15=12)
TREEIF_THRESHOLD:Bucket中链表长度大于该默认值,转化为红黑树:8
MIN_TREEIF_CAPACITY:桶中的Node被树化时最小的hash表容量:64

posted on 2021-07-30 10:57  余腾  阅读(187)  评论(0编辑  收藏  举报

Fork me on Gitee