-1

I just tried to implement a linked list and when I only added two elements, it threw NullPointerException in the toString method in the debugger, but I can't get why. It's OK while it's empty, it prints [], but then it throws an error. Maybe you could help me to figure out what's wrong with my toString() method?

The desirable output is [A, B, C] or [] if a list is empty.

My whole code:

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

public class ListImpl implements List {
    private Node head;
    private Node tail;

    private static class Node {
        Object data;
        Node next;

        Node(Object d) {
            data = d;
            next = null;
        }
    }

    @Override
    public void clear() {
        if (size() > 0) {
            head = null;
            tail = null;
        }
    }

    @Override
    public int size() {
        int size = 0;
        Node currentNode = head;
        while (currentNode != null) {
            size++;
            currentNode = currentNode.next;
        }
        return size;
    }

    public Iterator<Object> iterator() {
        return new IteratorImpl();
    }

    private class IteratorImpl implements Iterator<Object> {

        @Override
        public boolean hasNext() {
            return head != null;
        }

        @Override
        public Object next() {
            if(hasNext()){
                Object data = head.data;
                head = head.next;
                return data;
            }
            return null;
        }
    }

    @Override
    public void addFirst(Object element) {
        Node newNode = new Node(element);
        newNode.next = null;
        if (head == null) {
            head = newNode;
        }
        else {
            newNode.next = head;
            head = newNode;
        }
    }

    @Override
    public void addLast(Object element) {
        Node newNode = new Node(element);
        newNode.next = null;
        if (tail == null) {
            tail = newNode;
        }
        else {
            newNode.next = tail;
            tail = newNode;
        }
        
    }

    @Override
    public void removeFirst() {
        if (head == null) {
            System.err.print("The first element is absent");
        }
        head = head.next;
    }

    @Override
    public void removeLast() {
        if (head == null)
            System.err.print("Your list is empty");

        if (head.next == null) {
            System.err.print("There is only one element");
        }

        // Find the second last node
        Node second_last = head;
        while (second_last.next.next != null)
            second_last = second_last.next;

        // Change next of second last
        second_last.next = null;
    }

    @Override
    public Object getFirst() {
        if(head!=null) {
            return head.data;}
        else
            throw new java.util.NoSuchElementException("List is empty");
    }

    @Override
    public Object getLast() {
        if(head == null){
            throw new java.util.NoSuchElementException("List is empty");
        }
            Node last = head;
        while (last.next != null)
        {
            last = last.next;
        }
        return last;
    }

    @Override
    public Object search(Object element) {
        Object result = null;
        while (head.next != null)
        {
            if (head.data.equals(element)){
               result = head.data;
            }
        }
        return result;
    }

    @Override
    public boolean remove(Object element) {
        boolean isFound = false;
        if(head == null) {
            throw new NoSuchElementException("List is empty!");
        }
        if(head.data.equals(element)) {
            head = head.next;
            return true;
        }

        Node currentNode = head;
        Node previousNode = null;
        while(currentNode !=null) {
            if(currentNode.data.equals(element)) {
                isFound = true;
                break;
            }
            previousNode = currentNode;
            currentNode = currentNode.next;
        }
        if(currentNode == null) {
            return isFound;
        }
        currentNode = previousNode.next;
        previousNode.next = currentNode.next;
        currentNode.next = null;
        return isFound;
    }

    @Override
    public String toString() {
        Node current = head;
        if(head == null) {
            return "[]";
        }
       StringBuilder result = new StringBuilder();
        result.append("[");
        while(current.next != null) {
            result.append(current.data + ", ");
            current = current.next;
        }
        result.append(tail.data + "]");
        return result.toString();
    }

    public static void main(String[] args) {
    ListImpl list = new ListImpl();
    list.addFirst("FirstElement");
    list.addFirst("SecondElement");
        System.out.println(list);
    }
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197

1 Answers1

0

The problem is in the line

result.append(tail.data + "]");

You don't update the tail in the method addFirst() and in other methods too, if you correct that, it should work.

Feel free to add comments to my answer for clarifications.

Frighi
  • 475
  • 4
  • 17
  • I just chaned it to `@Override public void addFirst(Object element) { Node newNode = new Node(element); newNode.next = null; if (head == null) { head = newNode; tail = head; } else if (head == tail) { head = newNode; tail = head.next; } else { newNode.next = head; head = newNode; } }` But it still throws an exception :( – cunning_of_desires Jul 07 '21 at 20:10
  • You should draw your list on a piece of paper... Your changes are still not correct, in the "if" and "else if" body is missing the newNode.next set – Frighi Jul 07 '21 at 23:40