三、源码阅读
3、元素包含containsKey(Object key)
/**
* Returns <tt>true</tt> if this map contains a mapping for the
* specified key.
*
* @param key The key whose presence in this map is to be tested
* @return <tt>true</tt> if this map contains a mapping for the specified
* key.
*/
public boolean containsKey(Object key) {
return getNode(hash(key), key) !=
null;
}
/**
* Implements Map.get and related methods
*
* @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 &&
((k = first.key) == key || (key !=
null && key.equals(k))))
return first;
if ((e = first.next) !=
null) {
if (first
instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key !=
null && key.equals(k))))
return e;
}
while ((e = e.next) !=
null);
}
}
return null;
}
/**
* Calls find for root node.
*/
final TreeNode<K,V> getTreeNode(
int h, Object k) {
return ((parent !=
null) ? root() :
this).find(h, k,
null);
}
/**
* 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;
}
}
/**
* Finds the node starting at root p with the given hash and key.
* The kc argument caches comparableClassFor(key) upon first use
* comparing keys.
*/
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;
else if (ph < h)
p = pr;
else if ((pk = p.key) == k || (k !=
null && k.equals(pk)))
return p;
else if (pl ==
null)
p = pr;
else if (pr ==
null)
p = pl;
else if ((kc !=
null ||
(kc = comparableClassFor(k)) !=
null) &&
(dir = compareComparables(kc, k, pk)) !=
0)
p = (dir <
0) ? pl : pr;
else if ((q = pr.find(h, k, kc)) !=
null)
return q;
else
p = pl;
}
while (p !=
null);
return null;
}
4、get(Object key)
/**
* 返回value或null
*/
public V
get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) ==
null ?
null : e.value;
}
函数getNode在阅读笔记一中已经记录。
5、移除 remove(Object key)
/**
* Removes the mapping for the specified key from this map if present.
*
* @param key key whose mapping is to be removed from the map
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V
remove(Object key) {
Node<K,V> e;
return (e = removeNode(hash(key), key,
null,
false,
true)) ==
null ?
null : e.value;
}
/**
* Implements Map.remove and related methods
*
* @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 {
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.next;
++modCount;
--size;
afterNodeRemoval(node);
return node;
}
}
return 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 || root.right ==
null ||
(rl = root.left) ==
null || rl.left ==
null) {
tab[index] = first.untreeify(map);
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)
s = sl;
boolean c = s.red; s.red = p.red; p.red = c;
TreeNode<K,V> sr = s.right;
TreeNode<K,V> pp = p.parent;
if (s == pr) {
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) {
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);
}
方法 final void removeTreeNode暂时没有吃透,待后续补充。
四、小结
HashMap高性能需要以下几点: 1、高效的hash算法 2、保证hash值到内存地址(数组索引)的映射速度 3、根据内存地址(数组索引)可以直接得到相应的值
参考文章:https://yq.aliyun.com/articles/36812?spm=5176.8091938.0.0.lGqa1x
个人微信公众号:
作者:jiankunking 出处:http://blog.csdn.net/jiankunking