Skip to Content
Course content

190: Implementing a Custom Linked List

Click on the "Edit" button in the top corner of the screen to edit your slide content.

When you first start building your own data structures, it's easy to get tripped up by how Java handles references. I remember early in my career thinking that if I just "moved" a pointer past a node, that node was gone. It's a common misconception that leads to a very specific, frustrating bug.

Take a look at this implementation of a remove method for a custom singly linked list. On the surface, it looks logical: find the node with the target value, and then move on.

public void remove(int value) {
    Node current = head;
    while (current != null) {
        if (current.data == value) {
            // I found it! Now just skip it.
            current = current.next; 
            return;
        }
        current = current.next;
    }
}

The "Vanishing" Node That Doesn't Actually Vanish

If you run this code and then print your list, you'll notice something annoying: the node you tried to remove is still there. You didn't get a NullPointerException, and the code didn't crash; it just... didn't work.

Here is why: In Java, current is just a local reference variable. When you do current = current.next, you aren't changing the structure of the linked list; you're just changing which node the local variable current happens to be pointing to at that exact microsecond. The previous node in the list is still holding a reference to the node you want to delete. Since the chain isn't broken, the Garbage Collector won't touch that node, and it stays right where it was.

Tracking the Previous Node to Patch the Gap

To actually remove a node from a singly linked list, you have to change the next reference of the node before the one you're deleting. You need to "stitch" the previous node directly to the following node, effectively jumping over the victim.

The cleanest way to do this is to keep track of a previous pointer as you traverse. Here is how I would rewrite that logic:

public void remove(int value) {
    if (head == null) return;

    // Special case: removing the head
    if (head.data == value) {
        head = head.next;
        return;
    }

    Node current = head;
    Node previous = null;

    while (current != null) {
        if (current.data == value) {
            // The magic happens here: 
            // We tell the previous node to point to the one AFTER current.
            previous.next = current.next;
            return;
        }
        previous = current; // Keep track of where we were
        current = current.next;
    }
}

By updating previous.next, you've officially removed the node from the chain. The node that was once current is now unreachable from the head of the list, meaning Java's garbage collector will reclaim that memory.

Managing the Head and Tail Edge Cases

Whenever you implement a custom list, you have to obsess over the edges. I've seen countless production bugs caused by developers forgetting that the first and last elements behave differently.

  • The Head: If you remove the first element, there is no previous node. You must update the head reference itself, otherwise your list still starts at the node you intended to delete.
  • The Tail: If you remove the last element, current.next is null. My fix above handles this naturally because previous.next simply becomes null, correctly marking the new end of the list.
  • Empty Lists: Always check if head == null immediately. Trying to access head.data on an empty list is the fastest way to trigger a NullPointerException.



📋 Practical Task

Implement a "Remove Last" Method for a Custom Singly Linked List

You have been provided with a basic CustomLinkedList class that includes a Node inner class and an add(int value) method. Your task is to implement the removeLast() method.

Requirements:

  • The method should remove the very last node in the list.
  • If the list is empty, the method should do nothing.
  • If the list has only one element, the head should become null.
  • If the list has multiple elements, the second-to-last node's next reference must be set to null.
public class CustomLinkedList {
    private Node head;

    private static class Node {
        int data;
        Node next;
        Node(int data) { this.data = data; }
    }

    public void add(int value) {
        if (head == null) {
            head = new Node(value);
            return;
        }
        Node current = head;
        while (current.next != null) {
            current = current.next;
        }
        current.next = new Node(value);
    }

    public void removeLast() {
        // TODO: Implement this logic
    }

    public void printList() {
        Node current = head;
        while (current != null) {
            System.out.print(current.data + " -> ");
            current = current.next;
        }
        System.out.println("null");
    }
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.