JDK7: HashMap数据结构=数组+单链表, JDK8: HashMap数据结构=数组+单链表+红黑树。
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//默认初始容量2^4
static final int MAXIMUM_CAPACITY = 1 << 30;//最大容量2^30
容量必须是2的幂
static final float DEFAULT_LOAD_FACTOR = 0.75f;//默认加载因子
int threshold;// 扩容阈值 = 容量 x 加载因子,超过这个数就会触发扩容。
final float loadFactor;//实际加载因子
理想状态下哈希表的每个箱子中,元素的数量遵守泊松分布,加载因子为 0.75 时,泊松分布中 λ 约等于 0.5。
static final int TREEIFY_THRESHOLD = 8;//链表长度大于 8 时,有可能会转化成红黑树。
static final int UNTREEIFY_THRESHOLD = 6;//红黑树内数量 < 6时,则将红黑树转换成链表。
static final int MIN_TREEIFY_CAPACITY = 64;//链表长度大于 8而且键值对数量大于 64,才允许链表转换成红黑树。
出现链表长度8这种现象的概率小到忽略不计,一旦出现,几乎可以认为是哈希函数的设计有问题。
transient Node<K,V>[] table;//存放键值对数据的数组
transient Set<Map.Entry<K,V>> entrySet;//将数据转换成set的另一种存储形式,这个变量主要用于迭代功能。
transient int size;// HashMap中实际存储的键值对数量
transient int modCount;//HashMap在结构上被修改的次数,可用于判断ConcurrentModificationException。
transient反序列化的意思
static class Node<K,V> implements Map.Entry<K,V>//键值对数据
final int hash;//根据该值用来定位数组索引位置
final K key;
V value;
Node<K,V> next;//链表的下一个节点
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V>//红黑树
TreeNode<K,V> parent;// 父节点
TreeNode<K,V> left;//左子树
TreeNode<K,V> right;//右子树
TreeNode<K,V> prev;// 存储当前节点的前一个节点
boolean red;//颜色属性(红、黑)