void afterNodeRemoval(Node<K,V> e) { // unlink
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
//清理指针
p.before = p.after = null;
if (b == null){
//如果删除的是头结点,则重新设置头结点
head = a;
}else{
//重新设置前驱节点的后继节点
b.after = a;
}
if (a == null){
//如果删除的是尾结点,则重新设置尾节点
tail = b;
}else{
//重新设置后继节点的前驱节点
a.before = b;
}
}
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMap.Entry<K,V> last;
//accessOrder=true && 访问的不是尾节点
if (accessOrder && (last = tail) != e) {
LinkedHashMap.Entry<K,V> p =
(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
p.after = null;//清理后继节点指针,因为节点会被移到链表末尾
if (b == null){
//如果被访问节点是头结点,则将头结点指向头结点的后继节点
head = a;
}else{
//调整前驱节点的后继节点
b.after = a;
}
if (a != null){
//如果后继节点不为空,则更新后继节点的前驱节点
a.before = b;
}else{
//疑问:如果后继节点为null,则当前节点是尾结点(tail有可能为null?),而方法开始已经加了非尾节点的判断,为什么这里又判断一次呢?
//last 指向前驱节点
last = b;
}
if (last == null){
head = p;
}else {
//移到链表尾部
p.before = last;
last.after = p;
}
//更新尾节点指针
tail = p;
++modCount;
}
}
//LinkedHashMap
public boolean containsValue(Object value) {
for (LinkedHashMapEntry<K,V> e = head; e != null; e = e.after) {
V v = e.value;
if (v == value || (value != null && value.equals(v)))
return true;
}
return false;
}
//HashMap
public boolean containsValue(Object value) {
Node<K,V>[] tab; V v;
if ((tab = table) != null && size > 0) {
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next) {
if ((v = e.value) == value ||
(value != null && value.equals(v)))
return true;
}
}
}
return false;
}