HashMap可以理解为一个数组,数据根据计算出来的hash值存放,遍历顺序是不确定的,Java8之前,每个相同hashCode数组元素的值是用链表存放的,为单向链表,查找元素时间复杂度为O(N),Java8之后,如果同一个hashCode超过了8个值,则为了提高查找效率,在链表长度超过8时,则会将链表转换为红黑树,将查找元素时间复杂度提升到O(logN)。但是真正想要利用 JDK1.8 的好处,有一个限制: key的对象,必须正确的实现了 Compare 接口 如果没有实现 Compare 接口,或者实现得不正确(比方说所有 Compare 方法都返回0) 那 JDK1.8 的 HashMap 其实还是慢于 JDK1.7 的。
一、每个元素的数据结构:
HashMap中定义了一个实现了Map.Entry<k,v>的静态Entry<K,V>类,此类定义了如下(只摘录了最主要的部分):
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
final int hash;
/**
* Creates new entry.
*/
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
……略
}
可以看出该类是用来存放键值对的,并且通过next指向下一个实例实现链表结构。
二、HashMap的初始化方式:
//第一种
Map map = new HashMap();
// 第二种
Map map = new HashMap(int initialCapacity);
// 第三种
Map map = new HashMap(int initialCapacity, float loadFactor);
HashMap其实是一个存储数据的容器,涉及到容器初始化相关的,就会有相关大小的配置参数:
1. capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍,初始化为16。
2. loadFactor:负载因子,默认为 0.75,选择0.75作为默认的加载因子,完全是时间和空间成本上寻求的一种折衷选择。在理想情况下,使用随机哈希码,在扩容阈值(加载因子)为0.75的情况下,节点出现在频率在Hash桶(表)中遵循参数平均为0.5的泊松分布。可参考:https://blog.csdn.net/NYfor2017/article/details/105454097
3.threshold:扩容的阈值,等于 capacity * loadFactor
三、扩容
为了减少冲突的概率,当hashMap的数组长度到了一个临界值就会触发扩容,把所有元素rehash再放到扩容后的容器中。扩容的临界值由【加载因子】和当前容器的容量大小来确定:DEFAULT_INITIAL_CAPACITY*DEFAULT_LOAD_FACTOR ,即默认情况下是16x0.75=12时,就会触发扩容操作。
map的扩容,第一次是默认的容量(16),默认的扩容极限值(16 * 0.75 = 12);如果size达到12时,进行下次扩容,容量和极限值均扩容成原来的两倍,32,24;64,48.....,当然也有极限值,容量最大值为MAXiMUM_CAPACITY = 1 <<30,扩容临界值threshold = Integer.MAX_VALUE
四、链表和红黑树转换关系
若桶中链表元素超过8时,会自动转化成红黑树;若桶中元素小于等于6时,树结构还原成链表形式。
原因:
1、红黑树的平均查找长度是log(n),长度为8,查找长度为log(8)=3,链表的平均查找长度为n/2,当长度为8时,平均查找长度为8/2=4,这才有转换成树的必要;链表长度如果是小于等于6,6/2=3,虽然速度也很快的,但是转化为树结构和生成树的时间并不会太短。
2、6和8中间有个差值7可以防止链表和树之间频繁的转换。假设一下,如果设计成链表个数超过8则链表转换成树结构,链表个数小于8则树结构转换成链表,如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低。
五、线程安全
死循环和数据丢失是在JDK1.7中出现的问题,在JDK1.8中已经得到解决,然而1.8中仍会有数据覆盖这样的问题:【jdk 1.8插入是从尾部插入造成数据覆盖,jdk 1.7是从头部插入导致数据丢失或者死循环】
可参看:https://blog.csdn.net/swpu_ocean/article/details/88917958