原理简介:
HashMap是利用哈希表原理来存储元素的一种集合。在JDK1.7中,HashMap底层是 数组+链表 的, 在JDK1.8以后,HashMap底层改为 数组+链表+红黑树 构成, 效率也变的更高效。
HashMap源码主要从几个方面来看.
一 定义
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
继承AbstractMap 实现Map接口, Cloneable接口 ,能复制和序列化.
二 成员变量 (原理中必须要用到的几个重要参数)
private static final long serialVersionUID = 362498820763181265L; // UID 序列化用的.不解释 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16, 初始化的数组容量, 默认是16. 必须是2的倍数. static final int MAXIMUM_CAPACITY = 1 << 30; // 集合最大容量,1 << 30 为2的30次幂. 10亿多. static final float DEFAULT_LOAD_FACTOR = 0.75f; // 扩展因子, 0.75, 当数组中元素数量超过总容量的0.75倍(如默认容量16的0.75倍 12时,就会自动扩容) static final int TREEIFY_THRESHOLD = 8; // 树化阈值(JDK1.8新增), 8 ,也就是当链表中元素个数大于等于8时, 链表会转化为红黑树.对照下面的树退化阈值记忆. static final int UNTREEIFY_THRESHOLD = 6; // 树退化阈值(JDK1.8新增), 6, 当红黑树中元素个数少于等于6时, 红黑树会转化为链表. 呼应前面的树化阈值. static final int MIN_TREEIFY_CAPACITY = 64; // 当map中键值对总数量大于64时, 才会去判断上面的树化阈值.小于64时, 桶内元素太多只会扩容,不会化成树. //为了避免扩容和树形化选择冲突,这个值不能低于4*TREEIFY_THRESHOLD ,即32.
三 桶结构源码(从源码中可以看出,hash方式为key和value分别哈希,结果再异或)
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
浙公网安备 33010602011771号