一、定义
HashMap继承AbstractMap,实现Map、Cloneable、Serializable接口。其中,Map接口定义了一组通用的操作;Cloneable接口表示可以进行拷贝,在HashMap中,实现的是浅层次拷贝,Serializable接口表示HashMap实现了序列化。 Java8的HashMap对之前做了较大的优化,最重要的一个优化就是桶中的元素不再唯一按照链表组合,也可以使用红黑树进行存储。速度更快,性能得到了提升。
常量:
//默认初始容量(16)
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
//最大容量(2^30)
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//链表转换成树的阈值
static final int TREEIFY_THRESHOLD = 8;
//树转换成链表的阈值(执行resize操作时,当桶中bin的数量少于UNTREEIFY_THRESHOLD时使用链表来代替树)
static final int UNTREEIFY_THRESHOLD = 6;
//在转变成树之前,还会有一次判断,只有键值对数量大于 64 才会发生转换。
//这是为了避免在哈希表建立初期,多个键值对恰 好被放入了同一个链表中而导致不必要的转化。
static final int MIN_TREEIFY_CAPACITY = 64;
二、构造函数
(1) HashMap():构造一个具有默认初始容量(16)和默认加载因子(0.75)的空HashMap。
(2) HashMap(int initialCapacity):构造一个带指定初始容量和默认加载因子(0.75)的空HashMap。
(3) HashMap(int initialCapacity, float loadFactor):构造一个带指定初始容量和加载因子的空HashMap。
//有参构造器
public HashMap(int initialCapacity, float loadFactor) {
//初始容量不能<0
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
//最大容量不能>2^30
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
//加载因子不能<0
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
//设置HashMap的容量极限
this.threshold = tableSizeFor(initialCapacity);
}
/**
* 使用按位或计算容量极限
* Returns a power of two size for the given target capacity.
*/
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;
}
三、数据结构
从源码中可以看出,每次新建一个HashMap时,都会初始化一个哈希桶数组。table数组的元素为Node节点。
static class Node<K,V> implem