简介
HashMap最早出现在JDK1.2中,底层基于散列算法实现。HashMap 允许 null 键和 null 值,是非线程安全类,在多线程环境下可能会存在问题。
1.8版本的HashMap数据结构:
为什么有的是链表有的是红黑树?
默认链表长度大于8时转为树
结构
Node是HhaspMap中的一个静态内部类 :
//Node是单向链表,实现了Map.Entry接口
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;
}
// getter and setter ... toString ...
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;
}
}
TreeNode 是红黑树的数据结构。
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
TreeNode<K,V> parent; // red-black tree links
TreeNode<K,V> left;
TreeNode<K,V> right;
TreeNode<K,V> prev; // needed to unlink next upon deletion
boolean red;
TreeNode(int hash, K key, V val, Node<K,V> next) {
super(hash, key, val, next);
}
/**
* Returns root of tree containing this node.
*/
final TreeNode<K,V> root() {
for (TreeNode<K,V> r = this, p;;) {
if ((p = r.parent) == null)
return r;
r = p;
}
}
类定义
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
变量
/**
* 默认初始容量16(必须是2的幂次方)
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
/**
* 最大容量,2的30次方
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/**
* 默认加载因子,用来计算threshold
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* 链表转成树的阈值,当桶中链表长度大于8时转成树
threshold = capacity * loadFactor
*/
static final int TREEIFY_THRESHOLD = 8;
/**
* 进行resize操作时,若桶中数量少于6则从树转成链表
*/
static final int UNTREEIFY_THRESHOLD = 6;
/**
* 桶中结构转化为红黑树对应的table的最小大小
当需要将解决 hash 冲突的链表转变为红黑树时,
需要判断下此时数组容量,
若是由于数组容量太小(小于 MIN_TREEIFY_CAPACITY )
导致的 hash 冲突太多,则不进行链表转变为红黑树操作,
转为利用 resize() 函数对 hashMap 扩容
*/
static final int MIN_TREEIFY_CAPACITY = 64;
/**
保存Node<K,V>节点的数组
该表在首次使用时初始化,并根据需要调整大小。 分配时,
长度始终是2的幂。
*/
transient Node<K,V>[] table;
/**
* 存放具体元素的集
*/
transient Set<Map.Entry<K,V>> entrySet;
/**
* 记录 hashMap 当前存储的元素的数量
*/
transient int size;
/**
* 每次更改map结构的计数器
*/
transient int modCount;
/**
* 临界值 当实际大小(容量*填充因子)