11

我担心这是一个非常愚蠢的问题,但这里有:

为什么 Java 默认 LinkedList 实现中的 clear 方法会费心遍历列表并解开所有节点?为什么不直接解开标题并让列表的其余部分保持连接 - GC 无论如何都会得到它,不是吗?

这是方法:

/**
 * Removes all of the elements from this list.
 */
public void clear() {
    Entry<E> e = header.next;
    while (e != header) {
        Entry<E> next = e.next;
        e.next = e.previous = null;
        e.element = null;
        e = next;
    }
    header.next = header.previous = header;
    size = 0;
modCount++;
}

为什么走路呢?为什么不直接跳到header.next = header.previous = header;

我能想到的最好的结果是它对 GC 有帮助吗……?这个链接http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html#997442有点暗示。

蒂亚...

4

4 回答 4

19

他们的方法确保即使其他代码仍然持有对特定节点的引用,其他节点也会被 GC'ed。

否则,即使是对其中一个节点的单个外部引用也会阻止整个链被收集。

此外,列表中的其他操作可能同时进行(例如,通过subList()or Collections.unmodifiableList(),迭代器的视图),这确保了这些东西立即将列表视为“空”。

于 2009-02-22T22:48:36.817 回答
2

IIRC,这是在 JDK6 中进行的更改,以帮助某些(世代)GC 算法的性能。通常,List自身和较旧的节点将比其他一些节点位于较旧的一代中。年轻代会更频繁地被收集,结果年轻节点在发现所有节点都是垃圾之前就被复制了。

所以这是一个小的性能优化。内存性能优化有点奇怪,因为通常不是导致问题的代码需要额外的时间来执行。

于 2009-02-23T12:43:20.117 回答
0

我只是在我的游戏开发博客上推测这个问题。感谢你的回答。我认为节点暴露是一个有问题的设计余量。列表上的替代视图(迭代器等)将依赖节点取消链接来快速失败,这也是粗略的。与其依赖这种副作用行为,列表上的子视图应该检查修改计数。无论如何,我明白他们为什么现在坚持下去了。

于 2009-05-29T17:50:45.243 回答
0

http://developer.classpath.org/doc/java/util/LinkedList-source.html的java.util.LinkedList的源代码建议您可以简单地将第一个和最后一个元素设置为 null。

当然,如果你倾向于过度保护,你可以遍历整个事情。我个人认为,如果您的列表包含数千个元素,这可能是一项非常昂贵的任务。

于 2014-06-28T23:08:52.570 回答