【问题标题】:Java:Delete all the elements from Linked ListJava:删除链表中的所有元素
【发布时间】:2011-04-14 04:16:47
【问题描述】:

在Java中,如何使用已经可用的clear()方法删除链表中的所有元素without?这个练习的灵感来自电话采访中收到的一个问题。

假设我可以在 C 中做到这一点

void DeleteAllElement( ListElement **head ) {  
    ListElement *deleteMe = *head;  
    while( deleteMe )  {  
        ListElement *next = deleteMe->next;  
        delete deleteMe;  
        deleteMe = next;  
    }  
    *head = NULL;  
}

谢谢

【问题讨论】:

  • 每行缩进 4 个空格以获得自动“代码”块。已经有一个工具可以做到这一点:选择行并单击{} 图标。
  • 删除了我的答案,但实际上,为什么不使用 clear()。这就是它的用途。为什么要重新发明轮子?
  • 因为我在电话面试中被问到
  • 他们更有可能寻找 bdares 的答案

标签: java linked-list


【解决方案1】:

Java 具有自动垃圾回收功能,因此只需将 Head 引用设置为 null:

myList.headNode = null;

所以,假设我们有 LinkedList 类,它还有一个 resetList 函数...

public class LinkedList{
     private Node head;
     public Node find(Key k){ ... }
     public void add(Node n){ ... }
     ...
     public void reset(){ head = null;}
     public static void reset(LinkedList l){l.reset();}
}

如果我们不将 head 节点设为私有,我们可以简单地执行我发布的第一个代码 sn-p。

【讨论】:

  • 您需要将列表对头部的引用设置为空,而不是传递的引用。 DeleteAllElement 应该接受列表,而不是头节点,并将列表的头设置为null。否则,实际列表会保留对现有头部的引用。
  • 注意在你的答案中以代码的形式表达措辞,以便我接受?
【解决方案2】:

如果您谈论的是java.util.LinkedList 的实例:

    while (!linkedlist.isEmpty()) {
        linkedlist.removeFirst();
    }

如果您在谈论任何java.util.List 的实例:

    while (!list.isEmpty()) {
        list.remove(0);
    }

请记住,remove 是可选操作。但是,根据列表的实现,这可能非常高效。对于ArrayList,这样会更好:

    while (!list.isEmpty()) {
        list.remove(list.size() - 1);
    }

另一种选择是迭代列表并在每个元素上调用Iterator.remove() ...也是一个可选操作。 (但再一次,对于某些列表实现来说,这可能是非常低效的。)

如果您谈论的是自定义链表类,那么答案取决于您声明列表类内部数据结构的方式。


我怀疑如果面试官提到clear() 方法,他们期待的是标准 Java 集合框架上下文中的答案......而不是自定义链表类。

【讨论】:

    【解决方案3】:

    阅读实际代码很有用。我建议你看看。

    对于单链表,您可以像 @bdares 那样做,当您查看 java.util.LinkedList 的实际代码时(大多数开发人员使用的代码)建议,答案是完全不同的。

    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++;
    }
    

    首先要注意;这是用于向前和向后遍历的双向链表,它会积极清除所有引用。不知道为什么这样做是诚实的,因为 GC 会以任何方式清除这些 eup,而modCount 会在另一个线程中获取任何更改。实际上它应该首先执行 modCount。

    为了比较,这里是 ArrayList.clear();

    public void clear() {
        modCount++;
    
        // Let gc do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;
    
        size = 0;
    }
    

    【讨论】:

    • “不知道为什么会这样……” - 简短的回答:世代 GC。如果老年代中的列表节点引用了年轻代中的节点,则前者会阻止后者被年轻代收集器收集。这可能导致无法访问的列表节点的大规模使用。积极的归零可以避免这种情况。
    • (以及相关的列表元素......这可能比节点更重要。)
    【解决方案4】:
    for(i=0;i<linkedlist.size;i++){
      linkedlist.removeFirst();
    }
    

    或查看this example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-29
      • 2017-12-28
      • 1970-01-01
      • 1970-01-01
      • 2015-05-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-14
      相关资源
      最近更新 更多