概述
HashMap1.8-源码浅析2之HashMap初始化
- 初始化方法1——无参构造
- 初始化方法2——有参构造(initialCapacity,loadFactor)
- 初始化方法3——有参构造(Map<? extends K, ? extends V> )
注:我们都知道HashMap的结构是table数组+链表nodes/红黑树treeNodes组成。数组的元素里放着链表的头节点或红黑树的根节点。
提到这里,那么在读以前内容前,希望大家带着一个问题去读, table数组是什么时候初始化的?
初始化方法1——无参构造
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
//这里只是把默认的负载因子赋值到了loadFactor成员变量上,其他的什么都没做 table并没有初始化
}
初始化方法2——有参构造(initialCapacity,loadFactor)
/**
* 把loadFactor设值成默认的值DEFAULT_LOAD_FACTOR,没有初始化table
*/
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* 1.校验了传入的initialCapacity 容量和负载因子loadFactor
* 2.赋值loadFactor threshold(这是存的是实际要初始化的容量)
*/
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()方法
/**
* Returns a power of two size for the given target capacity.
* 这里就是返回一个 大于传入cap的值2次方的数中 最小的一个2次方数
* 比如:传入的是9 那么返回的是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;
}
初始化方法3——有参构造(Map<? extends K, ? extends V> )
/**
* 返回了一个新的HashMap类型的Map 这里是初始化了table的
*/
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);//返回了一个new出来的新的HashMap类型的Map
}
这里看一下putMapEntries(Map<? extends K, ? extends V> m, boolean evict)方法,在此方法中涉及到了扩容resize()和新增put()的操作,后面会有详说
/**
* 1.新new一个HashMap
* 2.把原Map的所有元素放入到新new出来的HashMap中
*/
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
if (table == null) { // pre-size
float ft = ((float)s / loadFactor) + 1.0F;
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
if (t > threshold)
threshold = tableSizeFor(t);
}
else if (s > threshold)
resize();//扩容
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
putVal(hash(key), key, value, false, evict);//新增
}
}
}
最后
以上就是真实早晨为你收集整理的HashMap1.8-源码浅析2之初始化的全部内容,希望文章能够帮你解决HashMap1.8-源码浅析2之初始化所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复