一、底层结构
数组+链表。
在使用无参构造方法时,默认先创建一个16位数组,每个数组上存储entry(K,V),多个entry将会形成链表。entry内部存储三个元素,键(K),值(V),链表的索引(next())。
hashmap底层有一个int modCount,被transient修饰,不会被序列化。每次对HashMap发生修改的操作时,都将会使modCount++。
二、put操作
将一个entry(K,V)放入HashMap时:
1、如果数组table为空,新建数组table;
2、如果K为空,return 调用putForNullKey(V)方法
3、计算hash(K)结果为H,本质是对K进行两次哈希操作。如果K instanceof String 为true,将会调用专门的return sun.misc.Hashing.stringHash32((String) k);
4、计算元素entry(K,V)的bucketIndex,计算公式为 H & (length - 1),length为数组长度。由于length必定为2的整数倍,所以计算公式等同于 H % length
5、如果bucketIndex上已经有了元素,那么就遍历链表上的所有旧有元素,针对新的entry(K,V),使用equals()方法比较新旧对象的K是否相同;
6、如果有两个对象的K相等,把就元素的V替换成新元素的V,并将V作为返回值返回;
7、如果没有相同的K,就把新元素作为链表表头元素,同时,将表头元素的next()方法指向旧元素;
8、返回null;
三、get操作
从一个HashMap通过get(K)取值时:
1、如果K为null,return 调用getForNullKey()方法;
2、调用getEntry(key)方法,获取key的entry;
3、返回null == entry ? null : entry.getValue();