一 HashMap底层数据结构
HashMap底层数据结构为散列表,结合了数组和链表+红黑树 的优势,
Node数据结构 hash值为key的hash值,
二 HashMap的主要属性
//默认Hash表的大小
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//Hash表最大大小
static final int MAXIMUM_CAPACITY = 1 << 30;
//默认加载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//链表转换为红黑树的 链表长度,和hash表的大小
static final int TREEIFY_THRESHOLD = 8;
static final int MIN_TREEIFY_CAPACITY = 64;
//红黑树转化为链表
static final int UNTREEIFY_THRESHOLD = 6;
//下面是第一次初始化的时候使用
//散列数组
transient Node<K,V>[] table;
//hash表中存储的key-value对的大小
transient int size;
//散列表结构发生改变的次数
transient int modCount;
//扩容阈值,当你的哈希表中的元素超过阈值时,触发扩容
int threshold;
//加载因子
final float loadFactor;
三 主要方法
计算key的hash值,这个地方将计算的hash值左移了16为,然后和hash值异或,为了使高16位也参与路由运算,减少了hash冲突
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
构造方法
参数 initialCapacity 初始化容量 loadFactor 加载因子
在构造函数中并没有对hash表经行初始化,在第一次添加数据的时候初始化
前面if判断 initialCapacity,initialCapacity的值必须大于等于0,且不能大于MAXIMUM_CAPACITY
loadFactor 不能小于等于0
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
tableSizeFor函数
对于输入的参数,返回一个大于等于当前值cap的一个数字,并且这个数字一定是2的次方数
比如 参数为 cap为9
n=8
0000 0000 0000 0000 0000 0000 0000 1000
| 0000 0000 0000 0000 0000 0000 0000 0100
0000 0000 0000 0000 0000 0000 0000 1100
| 0000 0000 0000 0000 0000 0000 0000 0011
0000 0000 0000 0000 0000 0000 0000 1111
| 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 1111
| 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 1111
return 15+1
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;
}
put方法,
hash key的哈希值,
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
//tab引用当前的hashMap,p 表示当前散列表的元素
//n hashMap的长度 i key的路由寻址结果
Node<K,V>[] tab; Node<K,V> p; int n, i;
//延迟初始化逻辑,第一次调用putVal时会初始化hashMap对象中的最耗费内存的散列表
if ((tab = table) == null || (n = tab