JDK11中的LinkedHashMap是死代码吗?
Is it dead code in LinkedHashMap in JDK11?
我正在阅读 JDK 11 中的 LinkedHashMap 源代码,我发现了一段死代码(我不确定)
众所周知,LinkedHashMap使用双向链表来保存所有elements.It的顺序,有一个成员叫accessOrder
final boolean accessOrder;
默认为 false,但如果设置为 true,每次 运行 get
,它都会将它到达的元素移动到链接的末尾 list.That是函数 afterNodeAccess
的作用。
//if accessOrder were set as true, after you visit node e, if e is not the end node of the linked list,
//it will move the node to the end of the linkedlist.
void afterNodeAccess(Node<K, V> e) {
LinkedHashMap.Entry<K, V> last;
if(accessOrder && (last = tail) != e) {
//if enter `if` ,it indicates that e is not the end of the linked list, because (last=tail!=e)
//then `a` as the after node of p(p is e after casting to LinkedHashMap.Entry) is never gonna be null. Only if p is last node of the linked list then a will be null.
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;
}
// Is the if else clasue redundant? `a` must not be null.. the else clase will never be excuted.
if(a != null) {
a.before = b;
} else {
last = b;
}
if(last == null) {
head = p;
} else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
所以我的问题来了:
(accessOrder && (last = tail) != e
表示e不是链表的最后一个节点。如果 e 已经是最后一个节点,我们什么都不用做,对吧?
则a
作为p的后节点,(p为LinkedHashMap.Entry后的e),不能为null。只有当 p
是最后一个节点时,a
才能为空。
那么下面这段代码有什么意义呢?
// Is the if else clasue redundant? `a` must not be null.. the else clase will never be excuted.
if(a != null) {
a.before = b;
} else {
last = b;
}
a
总是 != null
,else 子句 last = b
将永远不会被执行....所以它是死代码吗?
我还做了一个实验,将accessorder
设置为true
,然后我get
调试模式下的最后一个节点,似乎我永远无法进入上面否则计算 last = b
有什么建议吗?
OP中提供的代码是单链表的节点移除算法,将移除的节点设置为链表的尾部(重新定位到尾部):
LinkedHashMap.Entry<K, V> current = (LinkedHashMap.Entry<K, V>) e
LinkedHashMap.Entry<K, V> pred = current.before, succ = current.after;
current.after = null;
// position the successor of the removed node correctly
// (either as the head of the list or as the successor of the node BEFORE the removed node)
if(pred == null) {
head = succ;
} else {
pred.after = succ ;
}
// position the predecessor of the removed node correctly
// (either as the tail of the list or as the predecessor of the node AFTER the removed node)
if(succ != null) {
succ.before = pred;
} else { // unreachable for non tail nodes
last = pred;
}
// final step - if the predecessor of the removed node was null then the head
// of the list is the removed node (the list contains a single node).
// otherwise update the removed node as the tail of the list -
// its predecessor will be the previous tail of the list
if(last == null) { // unreachable for non tail nodes
head = current;
} else {
current.before = last;
last.after = current;
}
tail = current;
给定一个节点应重新定位为链接案例的尾部,此算法处理所有可能的案例。
在 afterNodeAccess
方法的上下文中,一般情况算法中会有一些冗余,因为由于 (last = tail) != e
,重新定位的节点永远不会位于列表的尾部。因此,更有效的算法是:
current.after = null;
// position the successor of the removed node correctly
// (either as the head of the list or as the successor of the node BEFORE the removed node)
if(pred == null) {
head = succ;
} else {
pred.after = succ ;
}
// position the predecessor of the removed node correctly
// (as the predecessor of the node AFTER the removed node)
// update the removed node as the tail of the list -
// its predecessor will be the previous tail of the list
succ.before = pred;
current.before = last;
last.after = current;
tail = current;
正如评论中提到的 holger - 这是一个经典的 'copy-paste' 解决方案,恕我直言,它表明在某些情况下重用代码似乎效率低下且不清楚。
根据 Johannes Kuhn 的建议,您可以考虑向 OpenJDK 社区提交对无法访问的代码的修复。请参阅有关如何完成此操作的参考资料。
参考文献:
我正在阅读 JDK 11 中的 LinkedHashMap 源代码,我发现了一段死代码(我不确定)
众所周知,LinkedHashMap使用双向链表来保存所有elements.It的顺序,有一个成员叫accessOrder
final boolean accessOrder;
默认为 false,但如果设置为 true,每次 运行 get
,它都会将它到达的元素移动到链接的末尾 list.That是函数 afterNodeAccess
的作用。
//if accessOrder were set as true, after you visit node e, if e is not the end node of the linked list,
//it will move the node to the end of the linkedlist.
void afterNodeAccess(Node<K, V> e) {
LinkedHashMap.Entry<K, V> last;
if(accessOrder && (last = tail) != e) {
//if enter `if` ,it indicates that e is not the end of the linked list, because (last=tail!=e)
//then `a` as the after node of p(p is e after casting to LinkedHashMap.Entry) is never gonna be null. Only if p is last node of the linked list then a will be null.
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;
}
// Is the if else clasue redundant? `a` must not be null.. the else clase will never be excuted.
if(a != null) {
a.before = b;
} else {
last = b;
}
if(last == null) {
head = p;
} else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
所以我的问题来了:
(accessOrder && (last = tail) != e
表示e不是链表的最后一个节点。如果 e 已经是最后一个节点,我们什么都不用做,对吧?
则a
作为p的后节点,(p为LinkedHashMap.Entry后的e),不能为null。只有当 p
是最后一个节点时,a
才能为空。
那么下面这段代码有什么意义呢?
// Is the if else clasue redundant? `a` must not be null.. the else clase will never be excuted.
if(a != null) {
a.before = b;
} else {
last = b;
}
a
总是 != null
,else 子句 last = b
将永远不会被执行....所以它是死代码吗?
我还做了一个实验,将accessorder
设置为true
,然后我get
调试模式下的最后一个节点,似乎我永远无法进入上面否则计算 last = b
有什么建议吗?
OP中提供的代码是单链表的节点移除算法,将移除的节点设置为链表的尾部(重新定位到尾部):
LinkedHashMap.Entry<K, V> current = (LinkedHashMap.Entry<K, V>) e
LinkedHashMap.Entry<K, V> pred = current.before, succ = current.after;
current.after = null;
// position the successor of the removed node correctly
// (either as the head of the list or as the successor of the node BEFORE the removed node)
if(pred == null) {
head = succ;
} else {
pred.after = succ ;
}
// position the predecessor of the removed node correctly
// (either as the tail of the list or as the predecessor of the node AFTER the removed node)
if(succ != null) {
succ.before = pred;
} else { // unreachable for non tail nodes
last = pred;
}
// final step - if the predecessor of the removed node was null then the head
// of the list is the removed node (the list contains a single node).
// otherwise update the removed node as the tail of the list -
// its predecessor will be the previous tail of the list
if(last == null) { // unreachable for non tail nodes
head = current;
} else {
current.before = last;
last.after = current;
}
tail = current;
给定一个节点应重新定位为链接案例的尾部,此算法处理所有可能的案例。
在 afterNodeAccess
方法的上下文中,一般情况算法中会有一些冗余,因为由于 (last = tail) != e
,重新定位的节点永远不会位于列表的尾部。因此,更有效的算法是:
current.after = null;
// position the successor of the removed node correctly
// (either as the head of the list or as the successor of the node BEFORE the removed node)
if(pred == null) {
head = succ;
} else {
pred.after = succ ;
}
// position the predecessor of the removed node correctly
// (as the predecessor of the node AFTER the removed node)
// update the removed node as the tail of the list -
// its predecessor will be the previous tail of the list
succ.before = pred;
current.before = last;
last.after = current;
tail = current;
正如评论中提到的 holger - 这是一个经典的 'copy-paste' 解决方案,恕我直言,它表明在某些情况下重用代码似乎效率低下且不清楚。
根据 Johannes Kuhn 的建议,您可以考虑向 OpenJDK 社区提交对无法访问的代码的修复。请参阅有关如何完成此操作的参考资料。
参考文献: