1.1 类图结构
注意这个table,就是我们HashMap底层的数组,这是一个Node数组,我们传入的键值对就是封装在这样的一个Node中后存放的。Node是HashMap的一个静态内部类,内部维护了一个next指针,指向的下一个Node,所以Node就是一个单向链表的节点。
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
}
1.2 加入元素与扩容机制分析
先根据以下测试代码进行debug来对HashMap的底层进行分析
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
for (int i = 0; i <= 80; i++) {
map.put(i, i + "");
}
}
首先调用HashMap的无参构造器
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
调用无参构造器的时候,会初始化加载因子,初始值采用默认值0.75
调用map的put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
- 计算传入key的hash值——调用hash()方法
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
这就是我们计算我们传入的key的hash值的方法,可以看到是调用了对象的hashcode方法;
计算key的hash值的目的就是为了在后面计算出当前传入的key应该放在table的哪个位置上。
调用putVal()方法
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K