1、HashMap的底层。
jdk1.7:数组 + 链表
jdk1.8:数组 + 链表 + 红黑树
2、关于HashMap的无参构造方法。
(1).HashMap的无参构造方法采用延迟加载的方式来进行数组初始化的,默认长度是16,扩容因子为12
static final float DEFAULT_LOAD_FACTOR = 0.75f;
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
这里并没有初始化数组,而是在put()方法的时候来完成数组的初始化的
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
transient Node<K,V>[] table;
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0){
tab = resize()
n=tab.length;
}
}
在这一行,Node<K,V>[] tab开始初始化。resize()中的部分代码
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
newCap = DEFAULT_INITIAL_CAPACITY;
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
(2).初始化方法:resize()
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1;
}
else if (oldThr > 0)
newCap = oldThr;
else {
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
if (oldTab != null) {
......
}
return newTab;
}
(3).threshold
threshold:扩容因子
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY && oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1;
}
总结:
threshold = (newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY));
newCap = DEFAULT_INITIAL_CAPACITY;
threshold = (newThr = oldThr << 1);
newCap = oldCap << 1;
作用:数组是否扩容是通过threshold扩容因子来进行判断,但是是按照数组容量的两倍来进行扩容的!
- 如果使用的是有参构造器HashMap(int initialCapacity, float loadFactor)
this.threshold = tableSizeFor(initialCapacity);
3、关于HashMap的有参构造方法。
static final int MAXIMUM_CAPACITY = 1 << 30;
有参构造器
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);
}
–>关于Float.isNaN(flaoat v)
public static boolean isNaN(float v) {
return (v != v);
}
扩容方法:tablesizefor()
当初始化HashMap时,如果指定了初始化容量initialCapacity,由于哈希桶的数量必须时2的n次幂,因此要把initialCapacity转化为
比它大的最小2的n次幂。
如传入的initialCapacity=3,数组实际容量为4;传入的initialCapacity=5,数组实际容量为8;传入的initialCapacity=15,数组实际容量为16;
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;
}
|