1.hashMap源码分析
hashmap由数组+链表组成的,数组是hashmap的主体,链表是为了解决哈希冲突而存在的。
static class Entry<k,v> implements map.Entry<k,v>{
final k key; //指的是map中的key
V value; //指的是value值
Entry<k,v> next; //Entry作为单位,指向下一个Entry对象
int hash; //通过key的hashcode的值来进行hash计算的值,来确定唯一的hash,避免重复计算。
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
在hashmap中,每个Entry作为一个单位进行一个相关的对象操作,也就是每一组数据进行hashMap的每一组数。
其中hashmap的默认长度是16.
其中hashmap是由数组+链表组成的,数组是hashmap的主体,链表则是主要为了了解解决哈希冲突而存在的,定位到数组位置不含链表(当前entry的next指向下一个为null)对于查找和添加是十分快的,仅仅只需要一次寻址就可以了,查找方式是根据key来进行equals进行查找来比对查找。
根据源码相关的解析可以得知:
transient int size这里是用来指实际存储key-value键值对个数。
其中hashmap的默认最小容量是16,该值是初始容量也就是16,一般是2的整数倍,根据源码解释:2^4为16
由此可知16的默认容量被填满之后threshold一般为capacity*loadfactory。hashmap在进行扩容时需要参考threshold,
threshold是负载因子,代表了table的填充度有多少,默认是0.75.
//负载因子,代表了table的填充度有多少,默认是0.75.
final float loadFactor;
transient int modcount;
//用于快速失败,由于hashmap非线程安全,在对hashmap进行迭代时,如果期间其他线程的参与导致hashmap的结构发生了变化(比如put,remove等操作),需要抛出异常。
/*
*其中hashmap一共有四个构造器:
*其中initalcapacity的默认容量是16,其中loadfactor是0.75
*/
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity); //默认的容量大小时2^4为16
if (initialCapacity > MAXIMUM_CAPACITY)
//其中maximum_capacity是最大容量,跟一下源码看一下具体的值。
initialCapacity = MAXIMUM_CAPACITY; //(最大为2^30为最大存储容量。)
if (loadFactor <= 0 || Float.isNaN(loadFactor)) //装载因子,如下所示:默认是0.75.
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity); //通过threshold进行一个扩容。
init();
//init()方法在hashmap中没有实际实现,不过在子类和linkedhashmap中就会有对应实现。
//从上面两行代码也可以看出来,在常规构造器中,并没有为数组分配内存空间。
}
根据源码显示可以得知,初始化容量大小为2^30,如下图所示: