HashMap
基于哈希表(数组,链表,红黑树)实现的映射
目录
HashMap继承关系
HashMap实现了Serializable接口,支持序列化,可通过序列化传输
HashMap实现了Cloneable接口,支持克隆
HashMap继承了AbstractMap抽象类,执行映射的基本操作
HashMap源码解析
静态 类Node:
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;
}
}
不可变 类KeySet:
final class KeySet extends AbstractSet<K> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
public final Iterator<K> iterator() { return new KeyIterator(); }
public final boolean contains(Object o) { return containsKey(o); }
public final boolean remove(Object key) {
return removeNode(hash(key), key, null, false, true) != null;
}
public final Spliterator<K> spliterator() {
return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super K> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K,V> e : tab) {
for (; e != null; e = e.next)
action.accept(e.key);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
}
不可变 类Values:
final class Values extends AbstractCollection<V> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
public final Iterator<V> iterator() { return new ValueIterator(); }
public final boolean contains(Object o) { return containsValue(o); }
public final Spliterator<V> spliterator() {
return new ValueSpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super V> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K,V> e : tab) {
for (; e != null; e = e.next)
action.accept(e.value);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
}
不可变 类EntrySet:
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
public final Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Node<K,V> candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e); // 比较键和值是否都相等
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null; // 删除节点
}
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (Node<K,V> e : tab) {
for (; e != null; e = e.next)
action.accept(e);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
}
抽象 类HashIterator及其子类KeyIterator,ValueIterator,EntryIterator:
abstract class HashIterator {
Node<K,V> next; // next entry to return
Node<K,V> current; // current entry
int expectedModCount; // 快速失败
int index; // current slot
HashIterator() {
expectedModCount = modCount;
Node<K,V>[] t = table; // table:存储Node的数组
current = next = null;
index = 0;
if (t != null && size > 0) { // advance to first entry
do {} while (index < t.length && (next = t[index++]) == null); // next = t[]的第一个非空节点Node
}
}
public final boolean hasNext() {
return next != null;
}
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null); // 非树结构:获取下一个非空节点Node
}
return e;
}
public final void remove() {
Node<K,V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
removeNode(p.hash, p.key, null, false, false);
expectedModCount = modCount;
}
}
final class KeyIterator extends HashIterator
implements Iterator<K> {
public final K next() { return nextNode().key; }
}
final class ValueIterator extends HashIterator
implements Iterator<V> {
public final V next() { return nextNode().value; }
}
final class EntryIterator extends HashIterator
implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
静态 类 HashMapSpliterator,及其子类KeySpliterator,ValueSpliterator,EntrySpliterator:
static class HashMapSpliterator<K,V> {
final HashMap<K,V> map;
Node<K,V> current; // current node
int index; // current index, modified on advance/split
int fence; // 最后一个索引
int est; // size estimate
int expectedModCount; // for comodification checks
HashMapSpliterator(HashMap<K,V> m, int origin,
int fence, int est,
int expectedModCount) {
this.map = m;
this.index = origin;
this.fence = fence;
this.est = est;
this.expectedModCount = expectedModCount;
}
final int getFence() { // initialize fence and size on first use
int hi;
if ((hi = fence) < 0) {
HashMap<K,V> m = map;
est = m.size;
expectedModCount = m.modCount;
Node<K,V>[] tab = m.table;
hi = fence = (tab == null) ? 0 : tab.length;
}
return hi;
}
public final long estimateSize() {
getFence(); // force init
return (long) est;
}
}
static final class KeySpliterator<K,V> extends HashMapSpliterator<K,V> implements Spliterator<K> {
KeySpliterator(HashMap<K,V> m, int origin, int fence, int est,
int expectedModCount) {
super(m, origin, fence, est, expectedModCount); // HashMapSpliterator构造函数
}
/**
* 分割映射
*/
public KeySpliterator<K,V> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid || current != null) ? null :
new KeySpliterator<>(map, lo, index = mid, est >>>= 1,
expectedModCount);
}
public void forEachRemaining(Consumer<? super K> action) {
int i, hi, mc;
if (action == null)
throw new NullPointerException();
HashMap<K,V> m = map;
Node<K,V>[] tab = m.table;
if ((hi = fence) < 0) {
mc = expectedModCount = m.modCount;
hi = fence = (tab == null) ? 0 : tab.length;
}
else
mc = expectedModCount;
if (tab != null && tab.length >= hi &&
(i = index) >= 0 && (i < (index = hi) || current != null)) {
Node<K,V> p = current;
current = null;
do {
if (p == null)
p = tab[i++];
else {
action.accept(p.key);
p = p.next;
}
} while (p != null || i < hi);
if (m.modCount != mc)
throw new ConcurrentModificationException();
}
}
public boolean tryAdvance(Consumer<? super K> action) {
int hi;
if (action == null)
throw new NullPointerException();
Node<K,V>[] tab = map.table;
if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {
while (current != null || index < hi) {
if (current == null)
current = tab[index++];
else {
K k = current.key;
current = current.next;
action.accept(k);
if (map.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
}
}
return false;
}
public int characteristics() {
return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
Spliterator.DISTINCT;
}
}
static final class ValueSpliterator<K,V> extends HashMapSpliterator<K,V> implements Spliterator<V> {
ValueSpliterator(HashMap<K,V> m, int origin, int fence, int est,
int expectedModCount) {
super(m, origin, fence, est, expectedModCount);
}
public ValueSpliterator<K,V> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid || current != null) ? null :
new ValueSpliterator<>(map, lo, index = mid, est >>>= 1,
expectedModCount);
}
public void forEachRemaining(Consumer<? super V> action) {
int i, hi, mc;
if (action == null)
throw new NullPointerException();
HashMap<K,V> m = map;
Node<K,V>[] tab = m.table;
if ((hi = fence) < 0) {
mc = expectedModCount = m.modCount;
hi = fence = (tab == null) ? 0 : tab.length;
}
else
mc = expectedModCount;
if (tab != null && tab.length >= hi &&
(i = index) >= 0 && (i < (index = hi) || current != null)) {
Node<K,V> p = current;
current = null;
do {
if (p == null)
p = tab[i++];
else {
action.accept(p.value);
p = p.next;
}
} while (p != null || i < hi);
if (m.modCount != mc)
throw new ConcurrentModificationException();
}
}
public boolean tryAdvance(Consumer<? super V> action) {
int hi;
if (action == null)
throw new NullPointerException();
Node<K,V>[] tab = map.table;
if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {
while (current != null || index < hi) {
if (current == null)
current = tab[index++];
else {
V v = current.value;
current = current.next;
action.accept(v);
if (map.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
}
}
return false;
}
public int characteristics() {
return (fence < 0 || est == map.size ? Spliterator.SIZED : 0);
}
}
static final class EntrySpliterator<K,V> extends HashMapSpliterator<K,V> implements Spliterator<Map.Entry<K,V>> {
EntrySpliterator(HashMap<K,V> m, int origin, int fence, int est,
int expectedModCount) {
super(m, origin, fence, est, expectedModCount);
}
public EntrySpliterator<K,V> trySplit() {
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid || current != null) ? null :
new EntrySpliterator<>(map, lo, index = mid, est >>>= 1,
expectedModCount);
}
public void forEachRemaining(Consumer<? super Map.Entry<K,V>> action) {
int i, hi, mc;
if (action == null)
throw new NullPointerException();
HashMap<K,V> m = map;
Node<K,V>[] tab = m.table;
if ((hi = fence) < 0) {
mc = expectedModCount = m.modCount;
hi = fence = (tab == null) ? 0 : tab.length;
}
else
mc = expectedModCount;
if (tab != null && tab.length >= hi &&
(i = index) >= 0 && (i < (index = hi) || current != null)) {
Node<K,V> p = current;
current = null;
do {
if (p == null)
p = tab[i++];
else {
action.accept(p);
p = p.next;
}
} while (p != null || i < hi);
if (m.modCount != mc)
throw new ConcurrentModificationException();
}
}
public boolean tryAdvance(Consumer<? super Map.Entry<K,V>> action) {
int hi;
if (action == null)
throw new NullPointerException();
Node<K,V>[] tab = map.table;
if (tab != null && tab.length >= (hi = getFence()) && index >= 0) {
while (current != null || index < hi) {
if (current == null)
current = tab[index++];
else {
Node<K,V> e = current;
current = current.next;
action.accept(e);
if (map.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
}
}
return false;
}
public int characteristics() {
return (fence < 0 || est == map.size ? Spliterator.SIZED : 0) |
Spliterator.DISTINCT;
}
}
静态不可变 类TreeNode:
/**
* 扩展自LinkedHashMap.Entry(它反过来扩展节点), 可用作普通节点或链接节点的扩展
* 红黑树(平衡二叉树)
*/
static final class TreeNode<K,V> extends LinkedHashMap.Entry<K,V> {
TreeNode<K,V> parent; // 父节点
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);
}
/**
* 返回包含此节点的红黑树的根节点
*/
final TreeNode<K,V> root() {
for (TreeNode<K,V> r = this, p;;) {
if ((p = r.parent) == null) // 查询其父节点
return r;
r = p;
}
}
/**
* TreeNode既是一个红黑树结构, 也是一个双链表结构
* 保证树的根节点成为链表的首节点
*/
static <K,V> void moveRootToFront(Node<K,V>[] tab, TreeNode<K,V> root) {
int n;
if (root != null && tab != null && (n = tab.length) > 0) { // 根节点不为空 && HashMap数组不为空
int index = (n - 1) & root.hash; // 根节点在数组中的位置
TreeNode<K,V> first = (TreeNode<K,V>)tab[index]; // 取得该位置上的第一个节点
if (root != first) {
// 该节点与root不同
Node<K,V> rn;
tab[index] = root; // 把数组index位置的元素替换为根节点
TreeNode<K,V> rp = root.prev; // 获取根节点的前驱节点
if ((rn = root.next) != null)
// 后继节点不为空:root后继节点的前驱节点指向root的前驱节点
// 相当于把root从链表中摘除
((TreeNode<K,V>)rn).prev = rp;
if (rp != null)
// root的前驱节点不为空
// root前驱节点的后继节点指向root的后继节点
rp.next = rn;
if (first != null) // 若数组首位置上的原元素不为空
first.prev = root; // 原首节点的前驱节点指向root
root.next = first; // 原首节点作为root的后继节点
root.prev = null; // root没有前驱节点
}
// 校验TreeNode对象是否满足红黑树和双链表的特性
// 不通过:用户编程失误/TreeNode实现问题
// 断言报错, 直接终止程序
assert checkInvariants(root);
}
/**
* 使用给定的hash和key从节点p开始查找
* kc参数在第一次使用比较键时缓存comparableClassFor(key)
*/
final TreeNode<K,V> find(int h, Object k, Class<?> kc) {
TreeNode<K,V> p = this;
do {
int ph, dir; K pk;
TreeNode<K,V> pl = p.left, pr = p.right, q;
if ((ph = p.hash) > h)
p = pl; // 节点P的哈希值 > 给定的哈希h, 则走向左子节点
else if (ph < h)
p = pr; // 节点P的哈希值 < 给定的哈希h, 则走向右子节点
else if ((pk = p.key) == k || (k != null && k.equals(pk)))
return p; // p.key == 给定的键k
else if (pl == null)
p = pr;
else if (pr == null)
p = pl;
else if ((kc != null ||
// comparableClassFor(k):若k是可比的, 则返回k, 否则返回null
(kc = comparableClassFor(k)) != null) &&
// compareComparables(kc, k, pk):若x.getClass() == kc返回 k.compareTo(x), 否则返回0
(dir = compareComparables(kc, k, pk)) != 0)
p = (dir < 0) ? pl : pr; // 两键相比:k.compareTo(pk) < 0 ? pl : pr
else if ((q = pr.find(h, k, kc)) != null) // 根据hash, key 和key.class查找节点
return q;
else
p = pl;
} while (p != null);
return null;
}
/**
* 若 parent != null
* 则:以此树的根节点root开始, 寻找节点
* 否则:以此节点this开始, 寻找节点
*/
final TreeNode<K,V> getTreeNode(int h, Object k) {
return ((parent != null) ? root() : this).find(h, k, null);
}
/**
* 用于在相等的哈希码和不可比较的情况下排序
*
* 先比较两个对象的类名, 类名是字符串对象, 按字符串的比较规则
* 若是同一个类型, 调用本地方法为两个对象生成hashCode值进行比较, hashCode <= 则返回 -1
*/
static int tieBreakOrder(Object a, Object b) {
int d;
if (a == null || b == null ||
// Object a 和 Object b 的类名相同
(d = a.getClass().getName().compareTo(b.getClass().getName())) == 0)
// 比较 a 和 b 的内存地址生成的 hash
d = (System.identityHashCode(a) <= System.identityHashCode(b) ? -1 : 1);
return d;
}
/**
* 通过TreeNode对象调用,实现该对象打头的链表转换为树结构
*/
final void treeify(Node<K,V>[] tab) {
TreeNode<K,V> root = null; // 定义树的根节点
for (TreeNode<K,V> x = this, next; x != null; x = next) { // 遍历链表, x指向当前节点, next指向下一个节点
next = (TreeNode<K,V>)x.next; // 下一个节点
x.left = x.right = null; // 设置当前节点的左右节点为空
if (root == null) {
// 如果还没有根节点
x.parent = null; // 当前节点的父节点设为空
x.red = false; // 当前节点的红色属性设为false(把当前节点设为黑色)
root = x; // 根节点指向到当前节点
}
else {
// 已经存在根节点
K k = x.key; // 取得当前链表节点的key
int h = x.hash; // 取得当前节点的hash值
Class<?> kc = null; // 定义key所属的Class
for (TreeNode<K,V> p = root;;) {
// 从根节点开始遍历, 此遍历没有设置边界, 只能从内部跳出
int dir, ph; // dir 标识方向(左右), ph标识当前树节点的hash值
K pk = p.key; // 当前树节点的key
if ((ph = p.hash) > h) // 当前树节点hash值 > 当前链表节点的hash值
dir = -1; // 标识当前链表节点会放到当前树节点的左侧
else if (ph < h)
dir = 1; // 右侧
/*
* 如果两个节点的key的hash值相等,那么还要通过其他方式再进行比较:
* 如果当前链表节点的key实现了comparable接口,并且当前树节点和链表节点是相同Class的实例,那么通过comparable的方式再比较两者
*
*/
else if ((kc == null &&
(kc = comparableClassFor(k)) == null) ||
(dir = compareComparables(kc, k, pk)) == 0)
// 若还是相等:通过tieBreakOrder进行比较
dir = tieBreakOrder(k, pk);
TreeNode<K,V> xp = p; // 保存当前树节点
/*
* 如果dir >=0 :当前链表节点一定放置在当前树节点的左侧
* 如果dir < 0 :当前链表节点一定放置在当前树节点的右侧
* 不一定是该树节点的左/右子节点, 也可能是更深层次的节点
*/
if ((p = (dir <= 0) ? p.left : p.right) == null) {
// 当前树节点是叶子节点
// 则根据dir的值把链表节点挂到树节点的左/右侧
x.parent = xp;
if (dir <= 0)
xp.left = x; // 作为左子节点
else
xp.right = x; // 作为右子节点
root = balanceInsertion(root, x); // 挂载后重新把树进行平衡
break;
}
/**
* 若当前树节点不是叶子节点
* 会以当前树节点的左子节点或者右子节点作起始节点, 从内循环处开始重新寻找自己(当前链表节点)的位置
*/
}
}
}
moveRootToFront(tab, root); // 把树的根节点设为其数组的首元素
}
/**
* 将树节点转换为非树节点
*/
final Node<K,V> untreeify(HashMap<K,V> map) {
Node<K,V> hd = null, tl = null;
for (Node<K,V> q = this; q != null; q = q.next) {
Node<K,V> p = map.replacementNode(q, null);
if (tl == null)
hd = p;
else
tl.next = p;
tl = p;
}
return hd;
}
/**
* 往树中插入节点
* 外层方法中对v进行写入
*/
final TreeNode<K,V> putTreeVal(HashMap<K,V> map, Node<K,V>[] tab,
int h, K k, V v) {
Class<?> kc = null; // 定义k的Class对象
boolean searched = false; // 标识是否已经遍历过一次树,未必是从根节点遍历的,但是遍历路径上一定已经包含了后续需要比对的所有节点。
TreeNode<K,V> root = (parent != null) ? root() : this; // 父节点不为空? 查找根节点: 自身作为根节点
for (TreeNode<K,V> p = root;;) {
// 从根节点开始遍历
int dir, ph; K pk;
if ((ph = p.hash) > h)
// 当前节点hash > 指定key的hash
// 代添加元素放置在当前节点的左侧
dir = -1;
else if (ph < h)
// 当前节点hash < 指定key的hash
// 代添加元素放置在当前节点的左侧
dir = 1;
else if ((pk = p.key) == k || (k != null && k.equals(pk)))
// 当前节点键对象 == 指定key对象, 则返回当前节点对象
return p;
// 当前节点的hash == 指定key的hash 但是 k.equals(pk) 不等
else if ((kc == null
// 指定key没有实现comparable接口
&& (kc = comparableClassFor(k)) == null)
// 实现了comparable接口且和当前节点的键对象比较之后相等(仅第一次循环)
|| (dir = compareComparables(kc, k, pk)) == 0) {
if (!searched) {
// 没有比对过当前节点的所有子节点
TreeNode<K,V> q, ch;
searched = true; // 标识已遍历节点的子节点
// 对树进行递归遍历查找和当前键equals相等的节点
// 短路运算:若左侧已找到, 右侧则不需遍历
if (((ch = p.left) != null &&
(q = ch.find(h, k, kc)) != null) ||
((ch = p.right) != null &&
(q = ch.find(h, k, kc)) != null))
return q; // 找到了指定key键对应元素
}
// 遍历所有子节点也没有找到和当前键equals相等的节点
// 再次比较当前节点键和指定key键的大小
dir = tieBreakOrder(k, pk);
}
TreeNode<K,V> xp = p; // 定义xp指向当前树节点
/*
* 若dir <= 0, 若左子节点为空, 则添加元素放到左子节点
* 若dir >= 0, 若右子节点为空, 则添加元素放到右子节点
* 若左/右子节点不为空, 则需进行下一轮比较
*
* 若其中有一个子节点不为空, p则指向对应的不为空的子节点
*/
if ((p = (dir <= 0) ? p.left : p.right) == null) {
// 若需添加方向上的子节点为空, 则节点p已指向这个空的子节点
Node<K,V> xpn = xp.next; // 获取当前节点xp的后继节点xpn
TreeNode<K,V> x = map.newTreeNode(h, k, v, xpn); // 创建一个新的树节点
if (dir <= 0)
xp.left = x; // xp左子节点指向新的树节点x
else
xp.right = x; // xp右子节点指向新的树节点x
xp.next = x; // xp的next节点指向到这个新的树节点x
x.parent = x.prev = xp; // 新树节点x的父节点和前驱节点均设置为当前的树节点xp
if (xpn != null) // 若原来的next节点不为空
((TreeNode<K,V>)xpn).prev = x; // 原next节点的前驱节点指向新的树节点
moveRootToFront(tab, balanceInsertion(root, x)); // 重新平衡, 新的根节点置顶
return null; // 返回null代表产生了一个新节点
}
}
}
/**
* Removes the given node, that must be present before this call.
* This is messier than typical red-black deletion code because we
* cannot swap the contents of an interior node with a leaf
* successor that is pinned by "next" pointers that are accessible
* independently during traversal. So instead we swap the tree
* linkages. If the current tree appears to have too few nodes,
* the bin is converted back to a plain bin. (The test triggers
* somewhere between 2 and 6 nodes, depending on tree structure).
*/
final void removeTreeNode(HashMap<K,V> map, Node<K,V>[] tab,
boolean movable) {
int n;
if (tab == null || (n = tab.length) == 0)
return;
int index = (n - 1) & hash;
TreeNode<K,V> first = (TreeNode<K,V>)tab[index], root = first, rl;
TreeNode<K,V> succ = (TreeNode<K,V>)next, pred = prev;
if (pred == null)
tab[index] = first = succ;
else
pred.next = succ;
if (succ != null)
succ.prev = pred;
if (first == null)
return;
if (root.parent != null)
root = root.root();
if (root == null
|| (movable
&& (root.right == null
|| (rl = root.left) == null
|| rl.left == null))) {
tab[index] = first.untreeify(map); // too small
return;
}
TreeNode<K,V> p = this, pl = left, pr = right, replacement;
if (pl != null && pr != null) {
TreeNode<K,V> s = pr, sl;
while ((sl = s.left) != null) // find successor
s = sl;
boolean c = s.red; s.red = p.red; p.red = c; // swap colors
TreeNode<K,V> sr = s.right;
TreeNode<K,V> pp = p.parent;
if (s == pr) { // p was s's direct parent
p.parent = s;
s.right = p;
}
else {
TreeNode<K,V> sp = s.parent;
if ((p.parent = sp) != null) {
if (s == sp.left)
sp.left = p;
else
sp.right = p;
}
if ((s.right = pr) != null)
pr.parent = s;
}
p.left = null;
if ((p.right = sr) != null)
sr.parent = p;
if ((s.left = pl) != null)
pl.parent = s;
if ((s.parent = pp) == null)
root = s;
else if (p == pp.left)
pp.left = s;
else
pp.right = s;
if (sr != null)
replacement = sr;
else
replacement = p;
}
else if (pl != null)
replacement = pl;
else if (pr != null)
replacement = pr;
else
replacement = p;
if (replacement != p) {
TreeNode<K,V> pp = replacement.parent = p.parent;
if (pp == null)
root = replacement;
else if (p == pp.left)
pp.left = replacement;
else
pp.right = replacement;
p.left = p.right = p.parent = null;
}
TreeNode<K,V> r = p.red ? root : balanceDeletion(root, replacement);
if (replacement == p) { // detach
TreeNode<K,V> pp = p.parent;
p.parent = null;
if (pp != null) {
if (p == pp.left)
pp.left = null;
else if (p == pp.right)
pp.right = null;
}
}
if (movable)
moveRootToFront(tab, r);
}
/**
* Splits nodes in a tree bin into lower and upper tree bins,
* or untreeifies if now too small. Called only from resize;
* see above discussion about split bits and indices.
*
* @param map the map
* @param tab the table for recording bin heads
* @param index the index of the table being split
* @param bit the bit of hash to split on
*/
final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {
TreeNode<K,V> b = this;
// Relink into lo and hi lists, preserving order
TreeNode<K,V> loHead = null, loTail = null;
TreeNode<K,V> hiHead = null, hiTail = null;
int lc = 0, hc = 0;
for (TreeNode<K,V> e = b, next; e != null; e = next) {
next = (TreeNode<K,V>)e.next;
e.next = null;
if ((e.hash & bit) == 0) {
if ((e.prev = loTail) == null)
loHead = e;
else
loTail.next = e;
loTail = e;
++lc;
}
else {
if ((e.prev = hiTail) == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
++hc;
}
}
if (loHead != null) {
if (lc <= UNTREEIFY_THRESHOLD)
tab[index] = loHead.untreeify(map);
else {
tab[index] = loHead;
if (hiHead != null) // (else is already treeified)
loHead.treeify(tab);
}
}
if (hiHead != null) {
if (hc <= UNTREEIFY_THRESHOLD)
tab[index + bit] = hiHead.untreeify(map);
else {
tab[index + bit] = hiHead;
if (loHead != null)
hiHead.treeify(tab);
}
}
}
/* ------------------------------------------------------------ */
// Red-black tree methods, all adapted from CLR
/**
* 红黑树左旋
*/
static <K,V> TreeNode<K,V> rotateLeft(TreeNode<K,V> root,
TreeNode<K,V> p) {
TreeNode<K,V> r, pp, rl;
if (p != null && (r = p.right) != null) {
// p和r都存在 && r是p的右子节点
if ((rl = p.right = r.left) != null)
// 存在r的左子节点
// 将 p.right = r 变成 p.right = r.left
// 将 rl.parent = r 变成 rl.parent = p
rl.parent = p;
if ((pp = r.parent = p.parent) == null)
// 存在p.parent == null
// 将 p.parent = r.parent = null
// 将 root.red = r.red = false
(root = r).red = false;
else if (pp.left == p)
// 存在 r.parent.left == p.parent.left == p
// 将 r.parent.left = p.parent.left = r
pp.left = r;
else
// 将 r.parent.right = p.parent.right = r
pp.right = r;
r.left = p;
p.parent = r;
}
return root;
}
/**
* 红黑树右旋
*/
static <K,V> TreeNode<K,V> rotateRight(TreeNode<K,V> root,
TreeNode<K,V> p) {
TreeNode<K,V> l, pp, lr;
if (p != null && (l = p.left) != null) {
// p和l都存在 && l是p的左子节点
if ((lr = p.left = l.right) != null)
// 存在l的右子节点
// 将 p.left = l 变成 p.left = l.right
// 将 lr.parent = l 变成 lr.parent = p
lr.parent = p;
if ((pp = l.parent = p.parent) == null)
// 若 l.parent == p.parent == null
// 将 root.red = l.red = false
(root = l).red = false;
else if (pp.right == p)
// 存在 l.parent.right == p.parent.right == p
// 将 l.parent.right = p.parent.right = l
pp.right = l;
else
// 将 r.parent.right = p.parent.right = r
pp.left = l;
l.right = p;
p.parent = l;
}
return root;
}
/**
* 添加节点时重新保持红黑树平衡
*/
static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root, TreeNode<K,V> x) {
// 新节点标为红色
x.red = true;
// xp:当前节点的父节点, xpp:爷爷节点, xppl:左叔叔节点, xppr:右叔叔节点
for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {
if ((xp = x.parent) == null) {
// 父节点为空, 则当前节点是根节点
// 标记为黑色, 返回
x.red = false;
return x;
}
else if (!xp.red || (xpp = xp.parent) == null)
// 父节点为黑色 || (父节点为红色 && 爷爷节点 == null)
return root;
if (xp == (xppl = xpp.left)) {
// 父节点 xp == 爷爷节点的左子节点 xpp.left
if ((xppr = xpp.right) != null && xppr.red) {
// 右叔叔xpp.right != null && xppr == 红色
xppr.red = false; // 右叔叔节点xppr 置为黑色
xp.red = false; // 父节点xp 置为黑色
xpp.red = true; // 爷爷节点xpp 置为红色
x = xpp;
// 进行下一轮循环, 爷爷节点xpp 当做处理的起始节点
}
else {
// 如果右叔叔节点 xppr == null || xppr.red == false
if (x == xp.right) {
// 当前节点x是父节点xp的右子节点
root = rotateLeft(root, x = xp); // 父节点xp左旋
xpp = (xp = x.parent) == null ? null : xp.parent; // 获取爷爷节点xpp
}
if (xp != null) {
xp.red = false; // 父节点xp置为黑色
if (xpp != null) {
xpp.red = true; // 爷爷节点置为 红色
root = rotateRight(root, xpp); //爷爷节点xpp右旋
}
}
}
}
else {
// 如果父节点xp是爷爷节点xpp的右子节点
if (xppl != null && xppl.red) {
// 左叔叔节点xppl是红色
xppl.red = false; // 左叔叔节点xppl 置为黑色
xp.red = false; // 父节点xp 置为黑色
xpp.red = true; // 爷爷节点xpp 置为红色
x = xpp;
// 进行下一轮循环, 爷爷节点xpp 当做处理的起始节点
}
else {
// 左叔叔节点xppr == null || xppr是黑色
if (x == xp.left) {
// 如果当前节点x是父节点xp的左子节点
root = rotateRight(root, x = xp); // 父节点xp做右旋
xpp = (xp = x.parent) == null ? null : xp.parent; // 获取爷爷节点
}
if (xp != null) {
xp.red = false; // 父节点xp置为黑色
if (xpp != null) {
xpp.red = true; // 爷爷节点xppr置为红色
root = rotateLeft(root, xpp); // 爷爷节点xpp做左旋
}
}
}
}
}
}
/**
* 删除节点时重新保持红黑树平衡
*/
static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
TreeNode<K,V> x) {
for (TreeNode<K,V> xp, xpl, xpr;;) {
if (x == null || x == root)
return root;
else if ((xp = x.parent) == null) {
x.red = false;
return x;
}
else if (x.red) {
x.red = false;
return root;
}
else if ((xpl = xp.left) == x) {
if ((xpr = xp.right) != null && xpr.red) {
xpr.red = false;
xp.red = true;
root = rotateLeft(root, xp);
xpr = (xp = x.parent) == null ? null : xp.right;
}
if (xpr == null)
x = xp;
else {
TreeNode<K,V> sl = xpr.left, sr = xpr.right;
if ((sr == null || !sr.red) &&
(sl == null || !sl.red)) {
xpr.red = true;
x = xp;
}
else {
if (sr == null || !sr.red) {
if (sl != null)
sl.red = false;
xpr.red = true;
root = rotateRight(root, xpr);
xpr = (xp = x.parent) == null ?
null : xp.right;
}
if (xpr != null) {
xpr.red = (xp == null) ? false : xp.red;
if ((sr = xpr.right) != null)
sr.red = false;
}
if (xp != null) {
xp.red = false;
root = rotateLeft(root, xp);
}
x = root;
}
}
}
else { // symmetric
if (xpl != null && xpl.red) {
xpl.red = false;
xp.red = true;
root = rotateRight(root, xp);
xpl = (xp = x.parent) == null ? null : xp.left;
}
if (xpl == null)
x = xp;
else {
TreeNode<K,V> sl = xpl.left, sr = xpl.right;
if ((sl == null || !sl.red) &&
(sr == null || !sr.red)) {
xpl.red = true;
x = xp;
}
else {
if (sl == null || !sl.red) {
if (sr != null)
sr.red = false;
xpl.red = true;
root = rotateLeft(root, xpl);
xpl = (xp = x.parent) == null ?
null : xp.left;
}
if (xpl != null) {
xpl.red = (xp == null) ? false : xp.red;
if ((sl = xpl.left) != null)
sl.red = false;
}
if (xp != null) {
xp.red = false;
root = rotateRight(root, xp);
}
x = root;
}
}
}
}
}
/**
* 校验TreeNode对象是否满足红黑树和双链表的特性
* 若不符合程序会抛出AssertionError并终止执行
*/
static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
tb = t.prev, tn = (TreeNode<K,V>)t.next;
//t的前驱结点不为空, 并且它的后继节点不为t
if (tb != null && tb.next != t)
return false;
//t的后继结点不为空, 并且它的前驱节点不为t
if (tn != null && tn.prev != t)
return false;
//t的父结点不为空, 并且它的左右孩子都不是t
if (tp != null && t != tp.left && t != tp.right)
return false;
//t的左孩子不为空 且 它的父结点不是t或者它的哈希值大于t的哈希值
if (tl != null && (tl.parent != t || tl.hash > t.hash))
return false;
//t的右孩子不为空 且 它的父结点不是t或者它的哈希值小于t的哈希值
if (tr != null && (tr.parent != t || tr.hash < t.hash))
return false;
//t && t的左孩子 && t的右孩子都不为空且都是红色结点
if (t.red && tl != null && tl.red && tr != null && tr.red)
return false;
//如果t的左孩子不为空, 则继续从左孩子开始检查
if (tl != null && !checkInvariants(tl))
return false;
//如果t的右孩子不为空, 则继续从右孩子开始检查
if (tr != null && !checkInvariants(tr))
return false;
return true;
}
}
HashMap构造方法:
/**
* 使用指定的初始容量和负载因子构造一个空HashMap
*
* @param initialCapacity the initial capacity
* @param loadFactor the load factor
* @throws IllegalArgumentException if the initial capacity is negative
* or the load factor is nonpositive
*/
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
this.threshold = tableSizeFor(initialCapacity);
}
/**
* 构造一个有指定初始容量和负载因子=0.75的空的HashMap
*
* @param initialCapacity the initial capacity.
* @throws IllegalArgumentException if the initial capacity is negative.
*/
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}
/**
* 构造一个有默认容量=16和默认负载因子=0.75的空的HashMap
*/
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
/**
* 使用与指定的map相同的映射构造一个新HashMap
* 新HashMap具有默认负载因子=0.75和足够容纳map的初始容量
*
* @param m the map whose mappings are to be placed in this map
* @throws NullPointerException if the specified map is null
*/
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}
/**
* 实现了Map的putAll 和 Map的构造函数
*
* @param m the map
* @param evict false when initially constructing this map, else
* true (relayed to method afterNodeInsertion).
*/
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
int s = m.size();
if (s > 0) {
if (table == null) {
// 初始table容量
float ft = ((float)s / loadFactor) + 1.0F;
int t = ((ft < (float)MAXIMUM_CAPACITY) ?
(int)ft : MAXIMUM_CAPACITY);
if (t > threshold)
threshold = tableSizeFor(t); // 为给定的目标容量返回两个大小的幂
}
else if (s > threshold)
// 加倍table的大小
resize();
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
K key = e.getKey();
V value = e.getValue();
putVal(hash(key), key, value, false, evict); // 插入映射
}
}
}
HashMap增删查方法:
/**
* 若这个map包含一个映射k->v
* 使得(key == null ? k == null : key.equals(k))
* 则该方法返回v, 否则返回null
*
* @see #put(Object, Object)
*/
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
/**
* 实现了Map的get和相关方法
*
* @param hash hash for key
* @param key the key
* @return the node, or null if none
*/
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k)))) // 哈希相等 且 键相等
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode) // first属于TreeNode, 则从first节点开始查询(树结构)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
// 从first的next节点开始查询(线性结构)
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
/**
* 将指定值value与此映射中的指定键key关联
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}.
* (A {@code null} return can also indicate that the map
* previously associated {@code null} with {@code key}.)
*/
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
/**
* 查找hash 和key都匹配的节点, 更新其值value
*
* @param hash hash for key
* @param key the key
* @param value the value to put
* @param onlyIfAbsent true:不改变已存在的值
* @param evict false:该表处于创建模式
* @return previous value, or null if none
*/
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length; // table == null, 初始化表的容量
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null); // 创建一个常规(非树)节点
else {
Node<K,V> e; K k;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
// hash相等 且 key相等, 返回目标节点
e = p;
else if (p instanceof TreeNode)
// 树结构
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); // 插入一个树节点
else {
// 链表
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null); // p.next == null 则新建一个节点
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash); // 链表树化
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
// hash相等 且 key相等, 抛出
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value; // 更新节点的值
afterNodeAccess(e); // LinkedHashMap的可用回调
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize(); // 扩容
afterNodeInsertion(evict); // LinkedHashMap的可用回调
return null;
}
/**
* 将指定映射的所有映射复制到此映射
* 这些映射将替换当前指定映射中任意键的映射
*
* @param m mappings to be stored in this map
* @throws NullPointerException if the specified map is null
*/
public void putAll(Map<? extends K, ? extends V> m) {
putMapEntries(m, true); // 插入映射
}
/**
* 如果键key存在, 则删除对应的映射
*
* @param key key whose mapping is to be removed from the map
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}.
* (A {@code null} return can also indicate that the map
* previously associated {@code null} with {@code key}.)
*/
public V remove(Object key) {
Node<K,V> e;
return (e = removeNode(hash(key), key, null, false, true)) == null ?
null : e.value;
}
/**
* 删除指定节点
*
* @param hash hash for key
* @param key the key
* @param value the value to match if matchValue, else ignored
* @param matchValue if true only remove if value is equal
* @param movable if false do not move other nodes while removing
* @return the node, or null if none
*/
final Node<K,V> removeNode(int hash, Object key, Object value,
boolean matchValue, boolean movable) {
Node<K,V>[] tab; Node<K,V> p; int n, index;
if ((tab = table) != null && (n = tab.length) > 0 &&
(p = tab[index = (n - 1) & hash]) != null) {
Node<K,V> node = null, e; K k; V v;
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
node = p;
else if ((e = p.next) != null) {
if (p instanceof TreeNode)
// 树结构, 查找树节点
node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
else {
// 链表结构, 以next得到下一个节点
do {
if (e.hash == hash &&
((k = e.key) == key ||
(key != null && key.equals(k)))) {
// 匹配节点则抛出
node = e;
break;
}
p = e;
} while ((e = e.next) != null);
}
}
if (node != null && (!matchValue || (v = node.value) == value ||
(value != null && value.equals(v)))) {
if (node instanceof TreeNode)
// 树结构删除节点
((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
else if (node == p)
// 数组结构删除节点
tab[index] = node.next;
else
// 链表结构删除节点:p.next 越过node指向node.next
p.next = node.next;
++modCount;
--size;
afterNodeRemoval(node); // LinkedHashMap的可用回调
return node;
}
}
return null;
}
/**
* 从该映射中删除所有映射
*/
public void clear() {
Node<K,V>[] tab;
modCount++;
if ((tab = table) != null && size > 0) {
size = 0;
for (int i = 0; i < tab.length; ++i)
tab[i] = null;
}
}
/**
* 获取指定键key的映射的值, 为null则返回默认值defaultValue
*/
@Override
public V getOrDefault(Object key, V defaultValue) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? defaultValue : e.value;
}
/**
* 给指定键key插入值, 若值已存在则不更新
*/
@Override
public V putIfAbsent(K key, V value) {
return putVal(hash(key), key, value, true, true);
}
/**
* 删除指定键key和指定值value的映射(key和value都需匹配)
*/
@Override
public boolean remove(Object key, Object value) {
return removeNode(hash(key), key, value, true, true) != null;
}
/**
* 更新指定键key的值(key和oldValue都需匹配)
*/
@Override
public boolean replace(K key, V oldValue, V newValue) {
Node<K,V> e; V v;
if ((e = getNode(hash(key), key)) != null &&
((v = e.value) == oldValue || (v != null && v.equals(oldValue)))) {
e.value = newValue;
afterNodeAccess(e); // LinkedHashMap的可用回调
return true;
}
return false;
}
/**
* 更新指定键key的值
*/
@Override
public V replace(K key, V value) {
Node<K,V> e;
if ((e = getNode(hash(key), key)) != null) {
V oldValue = e.value;
e.value = value;
afterNodeAccess(e); // LinkedHashMap的可用回调
return oldValue;
}
return null;
}
/**
* 如果指定键key的值不存在或为null
* 则使用给定的映射函数计算其值
* 若结果不为null则将新值输入并返回
*
* @throws ConcurrentModificationException if it is detected that the
* mapping function modified this map
*/
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
if (mappingFunction == null)
throw new NullPointerException();
int hash = hash(key);
Node<K,V>[] tab; Node<K,V> first; int n, i;
int binCount = 0;
TreeNode<K,V> t = null;
Node<K,V> old = null;
if (size > threshold || (tab = table) == null ||
(n = tab.length) == 0)
n = (tab = resize()).length; // table为null, 容量初始化
if ((first = tab[i = (n - 1) & hash]) != null) {
if (first instanceof TreeNode)
// 树结构
old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key); // 获取节点
else {
// 链表结构
Node<K,V> e = first; K k;
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
// key 和 hash 匹配
old = e;
break;
}
++binCount;
} while ((e = e.next) != null);
}
V oldValue;
if (old != null && (oldValue = old.value) != null) {
afterNodeAccess(old); // LinkedHashMap的可用回调
return oldValue;
}
}
int mc = modCount;
V v = mappingFunction.apply(key); // 对键key执行函数操作得到结果v
if (mc != modCount) { throw new ConcurrentModificationException(); }
if (v == null) {
return null;
} else if (old != null) {
old.value = v; // 更新值
afterNodeAccess(old); // LinkedHashMap的可用回调
return v;
}
else if (t != null)
// 树结构的更新值
t.putTreeVal(this, tab, hash, key, v);
else {
tab[i] = newNode(hash, key, v, first); // 新键非树节点
if (binCount >= TREEIFY_THRESHOLD - 1) // 超过 8 - 1
treeifyBin(tab, hash); // 把容器里的元素变成树结构
}
modCount = mc + 1;
++size;
afterNodeInsertion(true); // LinkedHashMap的可用回调
return v;
}
/**
* 如果指定键key的值存在且非空
* 则尝试在给定键及其当前映射值的情况下计算新值
* 计算结果为null则删除映射
*
* @throws ConcurrentModificationException if it is detected that the
* remapping function modified this map
*/
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (remappingFunction == null)
throw new NullPointerException();
Node<K,V> e; V oldValue;
int hash = hash(key);
if ((e = getNode(hash, key)) != null &&
(oldValue = e.value) != null) {
int mc = modCount;
V v = remappingFunction.apply(key, oldValue); // 执行计算
if (mc != modCount) { throw new ConcurrentModificationException(); }
if (v != null) {
// 替换e的值
e.value = v;
afterNodeAccess(e); // LinkedHashMap的可用回调
return v;
}
else
// 计算结果为null, 删除节点
removeNode(hash, key, null, false, true);
}
return null;
}
/**
* 以指定键key和其旧值
* 根据函数计算新值并替换映射中的就职
*
* @throws ConcurrentModificationException if it is detected that the
* remapping function modified this map
*/
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (remappingFunction == null)
throw new NullPointerException();
int hash = hash(key);
Node<K,V>[] tab; Node<K,V> first; int n, i;
int binCount = 0;
TreeNode<K,V> t = null;
Node<K,V> old = null;
if (size > threshold || (tab = table) == null ||
(n = tab.length) == 0)
n = (tab = resize()).length; // 初始化/扩容table容量
if ((first = tab[i = (n - 1) & hash]) != null) {
if (first instanceof TreeNode)
// 树结构
old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key); // 获取树节点
else {
// 线性结构
Node<K,V> e = first; K k;
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
// 获取节点
old = e;
break;
}
++binCount;
} while ((e = e.next) != null);
}
}
V oldValue = (old == null) ? null : old.value;
int mc = modCount;
V v = remappingFunction.apply(key, oldValue); // 函数运算
if (mc != modCount) { throw new ConcurrentModificationException(); }
if (old != null) {
if (v != null) {
old.value = v; // 赋值
afterNodeAccess(old);
}
else
// 计算结果为null, 删除节点
removeNode(hash, key, null, false, true);
}
else if (v != null) {
if (t != null)
// 树结构插值
t.putTreeVal(this, tab, hash, key, v);
else {
tab[i] = newNode(hash, key, v, first); // 新键非树节点
if (binCount >= TREEIFY_THRESHOLD - 1)
treeifyBin(tab, hash); // 把容器里的元素变成树结构
}
modCount = mc + 1;
++size;
afterNodeInsertion(true);
}
return v;
}
/**
* 若键key的映射值为null
* 则用value替换
* 否则用给定的重映射函数的结果替换关联的值
*
* @throws ConcurrentModificationException if it is detected that the
* remapping function modified this map
*/
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
if (value == null)
throw new NullPointerException();
if (remappingFunction == null)
throw new NullPointerException();
int hash = hash(key);
Node<K,V>[] tab; Node<K,V> first; int n, i;
int binCount = 0;
TreeNode<K,V> t = null;
Node<K,V> old = null;
if (size > threshold || (tab = table) == null ||
(n = tab.length) == 0)
n = (tab = resize()).length; // 初始化/扩容table容量
if ((first = tab[i = (n - 1) & hash]) != null) {
if (first instanceof TreeNode)
// 树结构
old = (t = (TreeNode<K,V>)first).getTreeNode(hash, key); // 获取节点
else {
// 线性结构
Node<K,V> e = first; K k;
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
old = e;
break;
}
++binCount;
} while ((e = e.next) != null);
}
}
if (old != null) {
V v;
if (old.value != null) {
int mc = modCount;
v = remappingFunction.apply(old.value, value); // 计算结果
if (mc != modCount) {
throw new ConcurrentModificationException();
}
} else {
v = value;
}
if (v != null) {
old.value = v;
afterNodeAccess(old);
}
else
// 删除节点
removeNode(hash, key, null, false, true);
return v;
}
if (value != null) {
if (t != null)
// 树结构插值
t.putTreeVal(this, tab, hash, key, value);
else {
tab[i] = newNode(hash, key, value, first); // 新建一个非树节点
if (binCount >= TREEIFY_THRESHOLD - 1)
treeifyBin(tab, hash); // 把容器里的元素变成树结构
}
++modCount;
++size;
afterNodeInsertion(true);
}
return value;
}
/**
* 创建一个常规(非树)节点
*/
Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
return new Node<>(hash, key, value, next);
}
/**
* 用于从树节点到普通节点的转换
*/
Node<K,V> replacementNode(Node<K,V> p, Node<K,V> next) {
return new Node<>(p.hash, p.key, p.value, next);
}
/**
* 创建一个树节点
*/
TreeNode<K,V> newTreeNode(int hash, K key, V value, Node<K,V> next) {
return new TreeNode<>(hash, key, value, next);
}
// For treeifyBin
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
return new TreeNode<>(p.hash, p.key, p.value, next);
}
// For treeifyBin
TreeNode<K,V> replacementTreeNode(Node<K,V> p, Node<K,V> next) {
return new TreeNode<>(p.hash, p.key, p.value, next);
}
/**
* 重置为初始默认状态
* 通过克隆和readObject调用
*/
void reinitialize() {
table = null;
entrySet = null;
keySet = null;
values = null;
modCount = 0;
threshold = 0;
size = 0;
}
// Called only from writeObject, to ensure compatible ordering.
void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
Node<K,V>[] tab;
if (size > 0 && (tab = table) != null) {
for (Node<K,V> e : tab) {
for (; e != null; e = e.next) {
s.writeObject(e.key);
s.writeObject(e.value);
}
}
}
}
HashMap的子视图方法:
/**
* 返回key的集
* @return a set view of the keys contained in this map
*/
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
/**
* 返回value的集合
* @return a view of the values contained in this map
*/
public Collection<V> values() {
Collection<V> vs = values;
if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
}
/**
* 返回映射的集
* @return a set view of the mappings contained in this map
*/
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
HashMap的其他方法:
/**
* 获取键key的哈希值
*/
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
/**
* 若x是可比的
* 则返回x
* 否则返回null
*/
static Class<?> comparableClassFor(Object x) {
if (x instanceof Comparable) {
Class<?> c; Type[] ts, as; ParameterizedType p;
if ((c = x.getClass()) == String.class) // bypass checks
return c;
if ((ts = c.getGenericInterfaces()) != null) {
for (Type t : ts) {
if ((t instanceof ParameterizedType) &&
((p = (ParameterizedType) t).getRawType() ==
Comparable.class) &&
(as = p.getActualTypeArguments()) != null &&
as.length == 1 && as[0] == c) // type arg is c
return c;
}
}
}
return null;
}
/**
* 若x.getClass() == kc返回 k.compareTo(x)
* 否则返回0
*/
@SuppressWarnings({"rawtypes","unchecked"}) // for cast to Comparable
static int compareComparables(Class<?> kc, Object k, Object x) {
return (x == null || x.getClass() != kc ? 0 :
((Comparable)k).compareTo(x));
}
/**
* 为给定的目标容量返回两个大小的幂
*/
static final int tableSizeFor(int cap) {
int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1);
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
/**
* 把容器里的元素变成树结构
*/
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize(); // 初始化/扩充 容量
else if ((e = tab[index = (n - 1) & hash]) != null) {
TreeNode<K,V> hd = null, tl = null;
do {
TreeNode<K,V> p = replacementTreeNode(e, null);
if (tl == null)
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
} while ((e = e.next) != null);
if ((tab[index] = hd) != null)
hd.treeify(tab);
}
}
/**
* 初始化或加倍表的容量
* 若表 == null:按照初始容量分配大小
* 否则:以2的幂偏移来增加容量
*
* @return the table
*/
final Node<K,V>[] resize() {
Node<K,V>[] oldTab = table;
int oldCap = (oldTab == null) ? 0 : oldTab.length;
int oldThr = threshold;
int newCap, newThr = 0;
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
// 旧容量 > 最大容量
threshold = Integer.MAX_VALUE;// 阈值设置为Integer的最大值
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
// 双倍扩大老内存和老阈值并赋给新的table
newThr = oldThr << 1;
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else {
// 初始化HashMap的默认参数
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
// 老阈值 > 0
// 新阈值 = 新容量 * 默认负载因子
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr; // 新阈值赋给当前table
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap]; // 创建容量为newCap的新table
table = newTab;
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {//对老table进行遍历
Node<K,V> e;
if ((e = oldTab[j]) != null) {//遍历到的赋给e进行暂存,同时将老table对应项赋值为null
oldTab[j] = null;
if (e.next == null)
// 创建一个新的空table, 重新进行元素的put, table长度是原table两倍
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
// 树的分割
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;// 用于保存put后不移位的链表
Node<K,V> hiHead = null, hiTail = null;// 用于保存put后移位的链表
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
// 将桶中的头结点添加到lohead和lotail
// 往后如果桶中还有不移位的结点, 就向tail继续添加
// lohead用于保存头结点的位置, lotaila用于判断是否到了末尾
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
//这是添加移位的结点, 与不移位的类似
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
// 把不移位的结点添加到对应的链表数组中去
loTail.next = null;
newTab[j] = loHead;
}
if (hiTail != null) {
// 把移位的结点添加到对应的链表数组中去
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}
return newTab;
}
HashMap总结
HashMap基于数组和链表和红黑树实现的存储结构。
HashMap是线程不安全的,无同步策略。
HashMap允许插入null元素。