5

I have implemented a Linked List into Java. I have created everything, but I am having difficulty removing a specific node with specific data. It is throwing a NullPointerException. I believe, I am getting a NullPointerException because the next node is null. If someone could please point me in the right direction that would be great.

Input

anything
one
two
three

exception:

Exception in thread "main" java.lang.NullPointerException
    at LinkedList.remove(LinkedList.java:28)
    at Main.main(Main.java:29)

Classes: Linked list class

public class LinkedList {

    // fields
    private Node head;
    private Node last;
    private int size = 0;

    // constructor, used when the class is first called
    public LinkedList() {
        head = last = new Node(null);
    }

    // add method
    public void add(String s) {
        last.setNext(new Node(s));
        last = last.getNext();
        size++;
    }

    // remove method, if it returns false then the specified index element doens not exist
    // otherwise will return true
    public boolean remove(String data) {
        Node current = head;
        last = null;
        while(current != null) {
            if(current.getData().equals(data)) {
                current = current.getNext();
                if(last == null) {
                    last = current;
                }else {
                    last.getNext().setNext(current);
                    size--;
                    return true;
                }
            }else {
                last = current;
                current = current.getNext();
            }
        }
        return false;
    }
    //will return the size of the list - will return -1 if list is empty
    public int size() {
        return size;
    }

    // will check if the list is empty or not
    public boolean isEmpty() {
        return true;
    }

    // @param (index) will get the data at specified index
    public String getData(int index) {

        if(index <= 0) {
            return null;
        }

        Node current = head.getNext();
        for(int i = 1;i < index;i++) {
            if(current.getNext() == null) {
                return null;
            }
            current = current.getNext();
        }

        return current.getData();
    }

    //@param will check if the arguement passed is in the list
    // will return true if the list contains arg otherwise false
    public boolean contains(String s) {
        for(int i = 1;i<=size();i++) {
            if(getData(i).equals(s)) {
                return true;
            }
        }
        return false;
    }

    //@return contents of the list - recursively 
    public String toString() {
        Node current = head.getNext();
        String output = "[";
        while(current != null) {
            output += current.getData()+",";
            current = current.getNext();
        }
        return output+"]";
    }

    //@return first node
    public Node getHead() {
        return head;
    }

    // @return (recursively) list
    public void print(Node n) {
        if(n == null) {
            return;
        }else {
            System.out.println(n.getData());
            print(n.getNext());
        }
    }
}

Main

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

    public static void main(String[] args) throws IOException{
        LinkedList list = new LinkedList(); // declaring main linked list
        LinkedList b_List = new LinkedList(); // declaring the backup list

        String input = null;
        // getting input from user, will stop when user has entered 'fin'
        while(!(input = br.readLine()).equals("fin")) {
            list.add(input); // adding to main list
            b_List.add(input);
        }

        list.print(list.getHead().getNext());

        System.out.println("Input Complete.");
        if(list.size() == 1) {
            System.out.println("You have entered only one name. He/She is the survior");
        }else {
            System.out.println("Enter the name(s) would like to remove: ");
            while(b_List.size() != 1) {
                String toRemove = br.readLine();
                b_List.remove(toRemove);
            }
        }
        System.out.println("The contestants were: ");
        list.print(list.getHead().getNext());
    }
}

node

public class Node {

    // Fields
    private String data;
    private Node next;

    // constructor
    public Node(String data) {
        this(data,null);
    }

    // constructor two with Node parameter
    public Node(String data, Node node) {
        this.data = data;
        next = node;
    }

    /**
     * Methods below return information about fields within class
     * */

    // @return the data
    public String getData() {
        return data;
    }

    // @param String data to this.data
    public void setData(String data) {
        this.data = data;
    }

    // @return next
    public Node getNext() {
        return next;
    }
    // @param Node next set to this.next
    public void setNext(Node next) {
        this.next = next;
    }

}
1
  • 1
    Question: why does an empty list imply size -1? Isn't the initial list (size 0) also empty? Commented Dec 19, 2011 at 5:19

4 Answers 4

5

First of all, your head is just a before-first marker so you shouldn't start the remove check from it.

Second, your remove method fails if node data is null

Third - your implementation is broken anyway because of last.getNext().setNext(current) - it won't link previous node with next, it will link current to next (i.e. will do nothing)

Fourth - it still fails to remove first element because of mysterious operations with last...

Correct implementation of remove would be something like this:

public boolean remove(String data){
    Node previous = head;
    Node current = head.getNext();
    while (current != null) {
        String dataOld = current.getData();
        if ((dataOld == null && data == null) || (dataOld != null && dataOld.equals(data))) {
            Node afterRemoved = current.getNext();
            previous.setNext(afterRemoved);
            if (afterRemoved == null) { // i.e. removing last element
                last = previous;
            }
            size--;
            return true;
        } else {
            previous = current;
            current = current.getNext();
        }
    }
    return false;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, it's Java 7 shortcut. I've edited the answer, now it should work for you.
0

Here we can see the simple implementation of LinkedList with iterator


    class LinkedList implements Iterable{
        private Node node;
        public void add(Object data){
            if(!Optional.ofNullable(node).isPresent()){
                node = new Node();
                node.setData(data);
            }else{
                Node node = new Node();
                node.setData(data);
                Node lastNode = getLastNode(this.node);
                lastNode.setNext(node);
            }
        }

        private Node getLastNode(Node node){
            if(node.getNext()==null){
                return node;
            }else{
                return getLastNode(node.getNext());
            }
        } 

        class Node{
            private Object data;
            private Node next;
            public Object getData() {
                return data;
            }
            public void setData(Object data) {
                this.data = data;
            }
            public Node getNext() {
                return next;
            }
            public void setNext(Node next) {
                this.next = next;
            }
        }

        public Iterator iterator() {
            return new NodeIterator();
        }

        class NodeIterator implements Iterator{
            private Node current;

            public boolean hasNext() {
                if(current == null){
                    current = node;
                    return Optional.ofNullable(current).isPresent();
                }else{
                    current = current.next;
                    return Optional.ofNullable(current).isPresent();
                }
            }

            public Node next() {
                return current;
            }
        }
    }

    public class LinkedListImpl {
        public static void main(String[] args) {
            LinkedList linkedList = new LinkedList();
            linkedList.add("data1");
            linkedList.add("data2");
            linkedList.add("data3");
            for(LinkedList.Node node: linkedList){
                System.out.println(node.getData());
            }
        }
    }

Comments

0

Here is Full Implementaion of Linked List

including insertion,deletion,searching,reversing,swaping,size,display and various important operations of linked list

import java.util.NoSuchElementException;
import java.util.Scanner;

class Node<T> {

    public Node<T> next;
    public T data;

    public Node() {

    }

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node [next=" + next + ", data=" + data + "]";
    }
}

class LinkedList<T> {

    Node<T> start = null;
    Node<T> end = null;

    public void insertAtStart(T data) {
        Node<T> nptr = new Node<T>(data, null);
        if (empty()) {
            start = nptr;
            end = start;
        } else {
            nptr.next = start;
            start = nptr;
        }
        display();
    }

    public void insertAtEnd(T data) {
        Node<T> nptr = new Node<T>(data, null);
        if (empty()) {
            insertAtStart(data);
            return;
        } else {
            end.next = nptr;
            end = nptr;
        }
        display();
    }

    public void insertAtPosition(int position, T data) {
        if (position != 1 && empty())
            throw new IllegalArgumentException("Empty");
        if (position == 1) {
            insertAtStart(data);
            return;
        }

        Node<T> nptr = new Node<T>(data, null);
        if (position == size()) {

            Node<T> startPtr = start;
            Node<T> endPtr = startPtr;
            while (startPtr.next != null) {
                endPtr = startPtr;
                startPtr = startPtr.next;
            }
            endPtr.next = nptr;
            nptr.next = end;
        } else {
            position -= 1;
            Node<T> startPtr = start;
            for (int i = 1; i < size(); i++) {
                if (i == position) {
                    Node<T> temp = startPtr.next;
                    startPtr.next = nptr;
                    nptr.next = temp;
                }
                startPtr = startPtr.next;
            }
        }
        display();
    }

    public void delete(int position) {

        if (empty())
            throw new IllegalArgumentException("Empty");

        if (position == 1) {
            start = start.next;
        } else if (position == size()) {
            Node<T> startPtr = start;
            Node<T> endPtr = start;
            while (startPtr.next != null) {
                endPtr = startPtr;
                startPtr = startPtr.next;
            }
            endPtr.next = null;
            end = endPtr;
        } else {
            position -= 1;
            Node<T> startPtr = start;
            for (int i = 1; i <= position; i++) {
                if (i == position) {
                    Node<T> temp = startPtr.next.next;
                    startPtr.next = temp;
                }
                startPtr = startPtr.next;
            }
        }
        display();
    }

    public int index(T data) {
        if (empty())
            throw new IllegalArgumentException("Empty");
        return index(start, data, 0);
    }

    private int index(Node<T> link, T data, int index) {
        if (link != null) {
            if (link.data == data) {
                return index;
            }
            return index(link.next, data, ++index);
        }
        return -1;
    }

    public void replace(int position, T data) {
        if (empty())
            throw new IllegalArgumentException("Empty");
        if (position == 1)
            start.data = data;
        else if (position == size())
            end.data = data;
        else {
            Node<T> startPtr = start;
            for (int i = 1; i <= position; i++) {
                if (i == position)
                    startPtr.data = data;
                startPtr = startPtr.next;
            }
        }
        display();
    }

    public void replaceRecursively(int position, T data) {
        replaceRecursively(start, position, data, 1);
        display();
    }

    private void replaceRecursively(Node<T> link, int position, T data, int count) {
        if (link != null) {
            if (count == position) {
                link.data = data;
                return;
            }
            replaceRecursively(link.next, position, data, ++count);
        }
    }

    public T middle() {
        if (empty())
            throw new NoSuchElementException("Empty");
        Node<T> slowPtr = start;
        Node<T> fastPtr = start;
        while (fastPtr != null && fastPtr.next != null) {
            slowPtr = slowPtr.next;
            fastPtr = fastPtr.next.next;
        }
        return slowPtr.data;
    }

    public int occurence(T data) {
        if (empty())
            throw new NoSuchElementException("Empty");
        return occurence(start, data, 0);
    }

    private int occurence(Node<T> link, T data, int occurence) {
        if (link != null) {
            if (link.data == data)
                ++occurence;
            return occurence(link.next, data, occurence);
        }
        return occurence;
    }

    public void reverseRecusively() {
        reverseRecusively(start);
        swapLink();
        display();
    }

    private Node<T> reverseRecusively(Node<T> link) {
        if (link == null || link.next == null)
            return link;
        Node<T> nextLink = link.next;
        link.next = null;
        Node<T> revrseList = reverseRecusively(nextLink);
        nextLink.next = link;
        return revrseList;
    }

    public void reverse() {
        if (empty())
            throw new NoSuchElementException("Empty");
        Node<T> prevLink = null;
        Node<T> currentLink = start;
        Node<T> nextLink = null;
        while (currentLink != null) {
            nextLink = currentLink.next;
            currentLink.next = prevLink;
            prevLink = currentLink;
            currentLink = nextLink;
        }
        swapLink();
        display();
    }

    private void swapLink() {
        Node<T> temp = start;
        start = end;
        end = temp;
    }

    public void swapNode(T dataOne, T dataTwo) {
        if (dataOne == dataTwo)
            throw new IllegalArgumentException("Can't swap " + dataOne + " and " + dataTwo + " both are same");
        boolean foundDataOne = false;
        boolean foundDataTwo = false;

        Node<T> dataOnePtr = start;
        Node<T> dataOnePrevPtr = start;
        while (dataOnePtr.next != null && dataOnePtr.data != dataOne) {
            dataOnePrevPtr = dataOnePtr;
            dataOnePtr = dataOnePtr.next;
        }

        Node<T> dataTwoPtr = start;
        Node<T> dataTwoPrevPtr = start;
        while (dataTwoPtr.next != null && dataTwoPtr.data != dataTwo) {
            dataTwoPrevPtr = dataTwoPtr;
            dataTwoPtr = dataTwoPtr.next;
        }

        if (dataOnePtr != null && dataOnePtr.data == dataOne)
            foundDataOne = true;

        if (dataTwoPtr != null && dataTwoPtr.data == dataTwo)
            foundDataTwo = true;

        if (foundDataOne && foundDataTwo) {

            if (dataOnePtr == start)
                start = dataTwoPtr;
            else if (dataTwoPtr == start)
                start = dataOnePtr;

            if (dataTwoPtr == end)
                end = dataOnePtr;
            else if (dataOnePtr == end)
                end = dataTwoPtr;

            Node<T> tempDataOnePtr = dataOnePtr.next;
            Node<T> tempDataTwoPtr = dataTwoPtr.next;

            dataOnePrevPtr.next = dataTwoPtr;
            dataTwoPtr.next = tempDataOnePtr;
            dataTwoPrevPtr.next = dataOnePtr;
            dataOnePtr.next = tempDataTwoPtr;

            if (dataOnePtr == dataTwoPrevPtr) {
                dataTwoPtr.next = dataOnePtr;
                dataOnePtr.next = tempDataTwoPtr;
            } else if (dataTwoPtr == dataOnePrevPtr) {
                dataOnePtr.next = dataTwoPtr;
                dataTwoPtr.next = tempDataOnePtr;
            }

        } else
            throw new NoSuchElementException("Either " + dataOne + " or " + dataTwo + " not in the list");
        display();
    }

    public int size() {
        return size(start, 0);
    }

    private int size(Node<T> link, int i) {
        if (link == null)
            return 0;
        else {
            int count = 1;
            count += size(link.next, 0);
            return count;
        }
    }

    public void printNthNodeFromLast(int n) {

        if (empty())
            throw new NoSuchElementException("Empty");

        Node<T> main_ptr = start;
        Node<T> ref_ptr = start;

        int count = 0;
        while (count < n) {
            if (ref_ptr == null) {
                System.out.println(n + " is greater than the no of nodes in the list");
                return;
            }
            ref_ptr = ref_ptr.next;
            count++;
        }

        while (ref_ptr != null) {
            main_ptr = main_ptr.next;
            ref_ptr = ref_ptr.next;
        }

        System.out.println("Node no " + n + " from the last is " + main_ptr.data);

    }

    public void display() {
        if (empty())
            throw new NoSuchElementException("Empty");
        display(start);
    }

    private void display(Node<T> link) {
        if (link != null) {
            System.out.print(link.data + " ");
            display(link.next);
        }
    }

    public boolean empty() {
        return start == null;
    }

}

public class LinkedListTest {

    public static void main(String[] args) {
        LinkedList<Integer> linkedList = new LinkedList<Integer>();
        boolean yes = true;
        Scanner scanner = new Scanner(System.in);
        do {
            System.out.println("\n1. Insert At Start");
            System.out.println("2. Insert At End");
            System.out.println("3. Insert at Position");
            System.out.println("4. Delete");
            System.out.println("5. Display");
            System.out.println("6. Empty status");
            System.out.println("7. Get Size");
            System.out.println("8. Get Index of the Item");
            System.out.println("9. Replace data at given position");
            System.out.println("10. Replace data at given position recusively");
            System.out.println("11. Get Middle Element");
            System.out.println("12. Get Occurence");
            System.out.println("13. Reverse Recusively");
            System.out.println("14. Reverse");
            System.out.println("15. Swap the nodes");
            System.out.println("16. Nth Node from last");
            System.out.println("\nEnter your choice");
            int choice = scanner.nextInt();

            switch (choice) {
            case 1:
                try {
                    System.out.println("Enter the item");
                    linkedList.insertAtStart(scanner.nextInt());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 2:
                try {
                    System.out.println("Enter the item");
                    linkedList.insertAtEnd(scanner.nextInt());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 3:
                try {
                    System.out.println("Enter the position");
                    int position = scanner.nextInt();
                    if (position < 1 || position > linkedList.size()) {
                        System.out.println("Invalid Position");
                        break;
                    }
                    System.out.println("Enter the Item");
                    linkedList.insertAtPosition(position, scanner.nextInt());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 4:
                try {
                    System.out.println("Enter the position");
                    int position = scanner.nextInt();
                    if (position < 1 || position > linkedList.size()) {
                        System.out.println("Invalid Position");
                        break;
                    }
                    linkedList.delete(position);
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 5:
                try {
                    linkedList.display();
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 6:
                System.out.println(linkedList.empty());
                break;

            case 7:
                try {
                    System.out.println(linkedList.size());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 8:
                try {
                    System.out.println(linkedList.index(scanner.nextInt()));
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 9:
                try {
                    System.out.println("Enter the position");
                    int position = scanner.nextInt();
                    if (position < 1 || position > linkedList.size()) {
                        System.out.println("Invalid Position");
                        break;
                    }
                    linkedList.replace(position, scanner.nextInt());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 10:
                try {
                    System.out.println("Enter the position");
                    int position = scanner.nextInt();
                    if (position < 1 || position > linkedList.size()) {
                        System.out.println("Invalid Position");
                        break;
                    }
                    System.out.println("Enter the item");
                    linkedList.replaceRecursively(position, scanner.nextInt());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 11:
                try {
                    System.out.println(linkedList.middle());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 12:
                try {
                    System.out.println("Enter the item");
                    System.out.println(linkedList.occurence(scanner.nextInt()));
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 13:
                try {
                    linkedList.reverseRecusively();
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 14:
                try {
                    linkedList.reverse();
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 15:
                try {
                    System.out.println("Enter the nodes");
                    linkedList.swapNode(scanner.nextInt(), scanner.nextInt());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            case 16:
                try {
                    System.out.println("Enter which node do you want from last");
                    linkedList.printNthNodeFromLast(scanner.nextInt());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;

            default:
                System.out.println("Invalid Choice");
                break;
            }
        } while (yes);
        scanner.close();
    }
}

Comments

0

Consider another possible implementation of a working non-recursive Linked List with generic T placeholder. It works out of the box and the code is a more simple one:

import java.util.Iterator;
import java.util.NoSuchElementException;

public class LinkedList<T> implements Iterable<T> {
    private Node first;
    private Node last;
    private int N;

    public LinkedList() {
        first = null;
        last = null;
        N = 0;
    }

    public void add(T item) {
        if (item == null) { throw new NullPointerException("Null object!"); }
        if (!isEmpty()) {
            Node prev = last;
            last = new Node(item, null);
            prev.next = last;
        }
        else {
            last = new Node(item, null);
            first = last;
        }
        N++;
    }

    public boolean remove(T item) {
        if (isEmpty()) { throw new IllegalStateException("Empty list!"); }
        boolean result = false;
        Node prev = first;
        Node curr = first;
        while (curr.next != null || curr == last) {
            if (curr.data.equals(item)) {
                // remove the last remaining element
                if (N == 1) { first = null; last = null; }
                // remove first element
                else if (curr.equals(first)) { first = first.next; }
                // remove last element
                else if (curr.equals(last)) { last = prev; last.next = null; }
                // remove element
                else { prev.next = curr.next; }
                N--;
                result = true;
                break;
            }
            prev = curr;
            curr = prev.next;
        }
        return result;
    }

    public int size() {
        return N;
    }

    public boolean isEmpty() {
        return N == 0;
    }

    private class Node {
        private T data;
        private Node next;

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

    public Iterator<T> iterator() { return new LinkedListIterator(); }

    private class LinkedListIterator implements Iterator<T> {
        private Node current = first;

        public T next() {
            if (!hasNext()) { throw new NoSuchElementException(); }
            T item = current.data;
            current = current.next;
            return item;
        }

        public boolean hasNext() { return current != null; }

        public void remove() { throw new UnsupportedOperationException(); }
    }

    @Override public String toString() {
        StringBuilder s = new StringBuilder();
        for (T item : this)
            s.append(item + " ");
        return s.toString();
    }

    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        while(!StdIn.isEmpty()) {
            String input = StdIn.readString();
            if (input.equals("print")) { StdOut.println(list.toString()); continue; }
            if (input.charAt(0) == ('+')) { list.add(input.substring(1)); continue; }
            if (input.charAt(0) == ('-')) { list.remove(input.substring(1)); continue; }
            break;
        }
    }
}

For more LinkedList examples, your can check out the article.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.