【问题标题】:NullPointerException when iterating over linked list遍历链表时出现 NullPointerException
【发布时间】:2014-03-21 20:50:50
【问题描述】:

代码背后的概念是删除列表中大于之前元素的元素。在这种情况下,我的节点有一个 int 数据,并且可以通过它进行比较。 (这些类在扩展 Comparable

问题是当这段代码与链表一起运行时,我得到一个空点异常:

 [2,5,4,3,7,6,4,2,3,4,5] 

应该得到的预期列表是

[2,2]

因为 (5 > 2) 删除 5 然后 (4 > 2) 删除 4 然后 (3 > 2) 删除 3 ... 以此类推,直到它以空指针异常结束。

另一个例子是列表

[3,1,-2,3,6,-1,3,2,1]

列表最终应该是

[3,1,-2]

其中的调试代码用于显示哪些元素已被删除。

getter 方法是基本的并且工作正常。

public void deleteIncrementing() {
    T largest = null;

    while(head.getNext() != null || head != null) {
        Node<T> temp = head.getNext();

        while(temp.getValue().compareTo(head.getValue()) > 0){
            largest = temp.getValue();
            remove(largest);
            System.out.println(largest); // debug
            if(temp.getNext() == null){
                break;
            }
            temp = head.getNext();
        }
        head = temp;
    }
}

源自建议的伪代码:

    Node<T> current = head;
    Node<T> previous = null;

    while(current != null) {
        if (previous != null){
            if (current.getValue().compareTo(previous.getValue()) > 0){
                //System.out.println(current.getValue().toString());
                remove(current.getValue());
            }
            if (current.getValue().compareTo(previous.getValue()) < 0){
                //System.out.println(previous.getPrevious().getValue().toString());
                //System.out.println(current.getValue().toString());
                remove(previous.getValue());
            }
        }

        previous = current;
        current  = current.getNext(); 
    }

哪个仍然不正确,因为它没有考虑到第一个到最后一个元素并保留最后一个元素...有什么原因吗?

【问题讨论】:

  • 我猜你应该删除 || 并在以下行中添加 &amp;&amp; while(head.getNext() != null || head != null)

标签: java nullpointerexception linked-list


【解决方案1】:

对于初学者来说,这个条件:

while (head.getNext() != null || head != null)

应该是:

while (head != null && head.getNext() != null)

始终检查空值首先

【讨论】:

    【解决方案2】:

    我不知道这是否是您出现异常的原因,但您必须在 while 循环中切换测试:

    while (head != null && head.getNext() != null)
    

    当您第一次测试 head.getNext() != null 并且 head 为 null 时,将抛出 NullPointerException

    For more information look here

    【讨论】:

      【解决方案3】:

      你在想这个问题。

      考虑你需要完成什么:编写一个函数,删除值大于前一个元素的值的 LinkedList 元素。

      阅读此声明后,您应该对 LinkedList 的每一点(例如当前元素和前一个元素)需要考虑的内容有所了解。所以真的不需要嵌套的while循环。

      伪代码:

      current  = head 
      previous = null
      
      while current is not null
         is previous non-null and current > previous?
            if yes: delete current
            if  no: do nothing
      
         previous = current
         current  = current.next 
      

      看看你是否可以使用这个伪代码来简化你自己的代码。

      【讨论】:

      • 将其改编为 java 代码并将其添加到主要问题中 - 仍然是空指针异常。但这确实更有意义。到目前为止感谢
      • 因为你做空检查不当
      • 还有其他方法可以检查 null....?或者你的意思是把它改成以前的 != null ?反过来,它不会产生写入输出,而是更接近。谢谢。
      • 问题不在于previous.getValue()为null,而是previous本身为null
      • 我想我改变了,它,但它仍然不正确。过去 30 分钟一直在摆弄,试图弄清楚为什么它不考虑这两个元素? (用新代码更新问题)
      【解决方案4】:

      除了其他人提到的对head的错误检查之外,我认为这还有一些潜在的问题:

          while(temp.getValue().compareTo(head.getValue()) > 0){
              largest = temp.getValue();
              remove(largest);
              System.out.println(largest); // debug
              if(temp.getNext() == null){
                  break;
              }
              temp = head.getNext();
          }
          head = temp;
      

      temp 将引用一个即将被删除的节点。该节点会发生什么?我不知道,因为我不知道这是什么列表类型或 remove 做什么。但是,除非列表类的文档明确指出remove 不会影响节点的“下一个”指针,否则我不会指望它。作为一般规则,此类数据应在remove 调用之前保存。 (在其他语言中,您可能有一个“删除”也显式释放存储空间,因此肯定需要先保存链接。)

      更严重的问题是,即使“下一个”指针保持不变,在列表末尾会发生什么。 temp 指向一个节点,然后将其删除。它的“下一个”指针是null,所以你打破了。但是随后您设置了head = temp,这意味着head 现在指向一个不再在列表中的节点。我认为你想要head = temp,只有当你因为compareTo而到达那一点时——而不是因为你到达列表的末尾。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多