HashMap 内部是如何存储数据的?工作原理是什么?
java1.7 hashMap 底层实现是数组+链表.
java1.8 hashMap 底层实现是数组+链表+红黑树.
1、hashmap 是怎么保存数据的?
在hashmap 中有这样一个结构
Node implenets Map.entity{
hash
key
value
next
}
当我们像hashMap 中放入数据时,其实就是一个
Enity{
key
vaue
}
在存之前会把这个Entity 转成Node
怎么转的如下:
根据Entity的key通过hash算出一个值,当成Node的hash,将key和vlaue复制到Node 中,对于没有产生hash 冲突前,Node的next是null.
复制完成后,还需要通过Entity对象的hash算出该Entiry对象具体应该放在hashMap 的哪个位置。
就是不同的元素通过Hash&(lenth-1) 公式算出的位置相同,现在就启动了链表(单项链表),挂在了当前位置的下面,而链表的元素怎么关联呢,就用到了Node的next ,next的值就是该链表下一个元素在内存中的地址。
jdk1.7就是这样处理的,而到了1.8以后,就引用了红黑树,1.8以后这个链表只让挂7个元素,超过七个就会转成一个红黑树进行处理(最多是64,超多64 就会重新拆分)。
hashMap扩容:
hashMap的初始容量默认是16,可以在new对象的时候,指定初始容量的大小,会根据当前的hashMap 的存储量达到 16*0.75=12 的时候,就是扩容16*2=32依次类推下去。2倍扩容。
扩容后元素是如何做到均匀分的。
对上面的总结:
1.7 的底层数据结构:
class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
int hash;
...
}
1.8 的底层数据结构:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
...
}
但基础结构还是: 数组 + 链表 ,称作 哈希表 或 散列表,只是 1.8 做了优化,引进了 红黑树 ,来提升链表中元素获取的速度。
JDK 1.7 采用头插法来添加链表元素,存在链表成环的问题,1.8 中做了优化,采用尾插法来添加链表元素。链表成环只是并发问题中的一种,1.8 虽然解决了此问题,但是还是会有很多其他的并发问题。