java - JDK11中LinkedHashMap中的死代码吗?

标签 java java-8 java-11 linkedhashmap dead-code

我正在阅读 JDK 11 中的 LinkedHashMap 源代码,我发现了一段死代码(我不确定)

众所周知,LinkedHashMap 使用双向链表来保存所有元素的顺序。它有一个成员叫accessOrder

final boolean accessOrder;

默认情况下它是假的,但如果它被设置为真,每次运行 get ,它将把它得到的元素移动到链表的末尾。这就是函数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),它不能为空。仅当 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 Debug模式下的最后一个节点,似乎我永远无法进入上述 else caluse 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在评论中提到 - 这是一个经典的“复制粘贴”解决方案,恕我直言,它表明在某些情况下重用代码似乎效率低下且不清楚。

正如 Johannes Kuhn 所建议的,您可以考虑向 OpenJDK 社区提交无法访问代码的修复程序。请参阅有关如何完成此操作的引用资料。

引用:
  • Source code from AdoptOpen JDK 11 for LinkedHashMap
  • How to contribute a fix to OpenJDK
  • 关于java - JDK11中LinkedHashMap中的死代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61634520/

    相关文章:

    java - 使用 Java 11 HttpClient 读取分块数据

    java - 使用 Apache poi 在 excel 中查找特定列中的最后一行 no

    java - 使用 Java 8 Stream API 过滤嵌套列表

    java - 错误 : Could not find or load main class application. 主要由 : java. 引起 lang.NoClassDefFoundError: javafx/application/Application JDK 11

    java - 查找没有哈希码的对象

    java - 将 Java 8 与 Google App Engine SDK 结合使用

    java - 在 Windows 10 上使用 OpenJDK 11 的 Eclipse 2018-09

    java - Controller 内部未接收到参数

    java - JVM 上的汇编编程?

    Java : why missing "new" operator while instantiating an object?