学习HashMap源码
构造方法
//初始容量
static final int DEFAULT_INITIAL_CAPACITY = 16;
//加载因子(超过HashMap底层数组容量的加载因子倍后,扩容)
static final float DEFAULT_LOAD_FACTOR = 0.75F;
//底层数组
static final HashMap.Entry<?, ?>[] EMPTY_TABLE = new HashMap.Entry[0];
//传入容量和加载因子
public HashMap(int var1, float var2) {
this.table = (HashMap.Entry[])EMPTY_TABLE;
this.hashSeed = 0;
this.entrySet = null;
if (var1 < 0) {
throw new IllegalArgumentException("Illegal initial capacity: " + var1);
} else {
if (var1 > 1073741824) {
var1 = 1073741824;
}
if (var2 > 0.0F && !Float.isNaN(var2)) {
this.loadFactor = var2;
this.threshold = var1;
this.init();
} else {
throw new IllegalArgumentException("Illegal load factor: " + var2);
}
}
}
//传入容量
public HashMap(int var1) {
this(var1, 0.75F);
}
//空参数,默认容量16,加载因子0.75F
public HashMap() {
this(16, 0.75F);
}
获取元素方法
public V get(Object var1) {
if (var1 == null) {
//hashmap的key可以是null
return this.getForNullKey();
} else {
//getEntry方法,是从数组中取hash值为索引的Entry对象
HashMap.Entry var2 = this.getEntry(var1);
return null == var2 ? null : var2.getValue();
}
}
添加元素方法
//添加方法,内部也是判断数组是否超容,如果没有,则将值放入数 组,超容的话,增大数组容量再赋值
public V put(K var1, V var2) {
if (this.table == EMPTY_TABLE) {
//初始化
this.inflateTable(this.threshold);
}
if (var1 == null) {
return this.putForNullKey(var2);
} else {
//计算Hash值
int var3 = this.hash(var1);
//查找var1在表的位置
int var4 = indexFor(var3, this.table.length);
for(HashMap.Entry var5 = this.table[var4]; var5 != null; var5 = var5.next) {
if (var5.hash == var3) {
Object var6 = var5.key;
if (var5.key == var1 || var1.equals(var6)) {
Object var7 = var5.value;
var5.value = var2;
var5.recordAccess(this);
return var7;
}
}
}
++this.modCount;
//增加Entry 没有找到Key
this.addEntry(var3, var1, var2, var4);
return null;
}
}
//初始化HashMap
private void inflateTable(int toSize) {
//计算出大于toSize最临近的2的N此方的值
//假设此处传入6, 那么最临近的值为2的3次方,也就是8
int capacity = roundUpToPowerOf2(toSize);
//由此处可知:threshold = capacity * loadFactor
threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
//创建Entry数组,这个Entry数组就是HashMap所谓的容器
table = new Entry[capacity];
initHashSeedAsNeeded(capacity);
}
总结
HashMap只允许一个为null的key。
HashMap默认容量:16;它的扩容:当前table数组的两倍
HashMap实际能存储的元素个数: capacity * loadFactor
HashMap在扩容的时候,会重新计算hash值,并对hash的位置进行重新排列, 因此,为了效率,尽量给HashMap指定合适的容量,避免多次扩容