You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义LinkedList类first节点引用为空及last节点异常问题求助

Hey Tony, let's walk through the issues in your LinkedList code one by one—most of your problems come from accidental modifications to your first/last pointers and incorrect node linking:

1. The size() method is destroying your first pointer

Your size() method modifies the class-level first variable directly when traversing:

public int size(){
    int c = 0;
    while(first != null){
        first = first.next; // This moves the original first pointer to null after traversal!
        c++;
    }
    return c;
}

After calling L.size(), your first node gets set to null—that's why all subsequent operations fail. Never modify your core list pointers when just reading data. Instead, use a temporary variable to traverse:

public int size(){
    int c = 0;
    Node current = first; // Use a temp variable instead of modifying first
    while(current != null){
        current = current.next;
        c++;
    }
    return c;
}

2. Incorrect addLast() implementation

Your addLast() has two critical bugs:

  • You traverse the list (unnecessarily, since you have a last pointer) and then create two separate new nodes: one for last.next and another for last itself. This disconnects last from the actual list.
  • You don't handle the case where first is null properly (the code after the if block will run even if p is null, causing a NullPointerException).

Fix it by leveraging your last pointer directly:

public void addLast(T value){
    Node newNode = new Node(value, null);
    if(first == null){ // List is empty
        first = last = newNode;
        return;
    }
    // Link the new node to the end, then update last
    last.next = newNode;
    last = newNode;
}

3. Broken constructor

Your constructor creates two separate nodes for first and last, which means your initial list has two disconnected nodes with the same value:

public LinkedList(T value) {
    temp = new Node(value,null);
    first = new Node(value,null);
    last = temp;
}

Simplify it to create a single node and point both first and last to it:

public LinkedList(T value) {
    Node initialNode = new Node(value, null);
    first = initialNode;
    last = initialNode;
    temp = initialNode; // If you even need temp—looks like it's unused in your code
}

(Side note: The temp variable seems unused; you can probably remove it entirely to avoid confusion.)

4. Minor issue: remove() edge case handling

When removing the last node, you need to update the last pointer to point to the previous node. Otherwise, last will still reference the removed node. We added this logic to the helper removeLL() method.

Fixed Full Code

Here's the corrected version of your class with all fixes applied:

public class LinkedList<T> {
    Node first, last; // Removed unused temp variable

    public class Node {
        T value;
        Node next;

        public Node(T value, Node next) {
            this.value = value;
            this.next = next;
        }

        public String toString() {
            if (next == null) {
                return value.toString();
            } else {
                return value.toString() + " " + next.toString();
            }
        }

        public T getLL(int index) {
            if (index == 0) {
                return value;
            }
            if (next == null) {
                throw new IndexOutOfBoundsException("have reached the end of the list, none found");
            }
            return next.getLL(index - 1);
        }

        // Helper method to handle remove and update last if needed
        public T removeLL(int x, LinkedList<T> list) {
            if (x == 1) {
                T removedValue = next.value;
                // If we're removing the last node, update list.last
                if (next == list.last) {
                    list.last = this;
                }
                next = next.next;
                return removedValue;
            } else if (next == null) {
                throw new IndexOutOfBoundsException("have reached the end of the list, none found");
            } else {
                return next.removeLL(x - 1, list);
            }
        }
    }

    public LinkedList(T value) {
        Node initialNode = new Node(value, null);
        first = initialNode;
        last = initialNode;
    }

    public static void main(String[] args) {
        /**
         * [120,110,100,90,80];
         */
        LinkedList<Integer> L = new LinkedList<>(100); // Use generic type to avoid warnings
        L.addFirst(110);
        L.addFirst(120);
        L.addLast(90);
        L.addLast(80);
        System.out.println(L.size()); // Should print 5
        System.out.println(L.remove(0)); // Should print 120
        System.out.println(L.last.toString()); // Should print 80
        System.out.println(L.first.toString()); // Should print 110 100 90 80
    }

    public void addFirst(T value) {
        first = new Node(value, first);
        // If list was empty before, update last too
        if (last == null) {
            last = first;
        }
    }

    public void addLast(T value) {
        Node newNode = new Node(value, null);
        if (first == null) {
            first = last = newNode;
            return;
        }
        last.next = newNode;
        last = newNode;
    }

    public T get(int index) {
        if (first == null) {
            throw new IndexOutOfBoundsException("empty list");
        }
        return first.getLL(index);
    }

    public int size() {
        int c = 0;
        Node current = first;
        while (current != null) {
            current = current.next;
            c++;
        }
        return c;
    }

    public T remove(int x) {
        if (first == null) {
            throw new IndexOutOfBoundsException("Tried to remove from empty list");
        }
        if (x == 0) {
            T removedValue = first.value;
            first = first.next;
            // If list is now empty, update last
            if (first == null) {
                last = null;
            }
            return removedValue;
        }
        return first.removeLL(x, this);
    }
}

Why This Works

  • The size() method no longer modifies the original first pointer.
  • addLast() correctly links new nodes to the end of the list and updates last properly.
  • The constructor initializes first and last to the same node, so your initial list is properly linked.
  • We added handling to update last when removing the last node, keeping your list pointers consistent.

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:23:05