4

When calling my iterator over a doubly linked list, I am getting a null pointer exception. The null pointer exception occurs in main at line assertEquals(i, (int) it.next());

     /***************************
      * nested class DequeIterator
      ***************************/
     private class DequeIterator implements Iterator<E>
      {
        // instance data member of ListIterator
        private Node current;

        // constructors for ListIterator
        public DequeIterator()
        {
          current = first; // head in the enclosing list
        }

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

        public E next()
        {
          if (hasNext() == false){ throw new NoSuchElementException();}
          else {
          E ret = current.item;
          current = current.next;
          return ret;
          }
        }

public void addLast(E item) {

        if (item.equals(null)) { throw new NullPointerException(); }

        else {

        Node node = new Node(item, null);
        Node ptr = last;

        ptr.prev.next = node;
        node.next = ptr;
        node.prev = ptr.prev;
        ptr.prev = node;    
        N++;

        }
    }

public static void main(String[] args) {

        Deque<Integer> lst = new Deque<Integer>(); // empty list


        for(int i = 1; i <= 5; i++) {
              lst.addLast(i);
            }
        assertEquals(5, lst.size());
        Iterator<Integer> it = lst.iterator();
        int i = 1;
        while(it.hasNext()) {
          assertEquals(i, (int) it.next());
          i++;
        }
        assertEquals(6, i);
        assertEquals(5, lst.size());
}

Can anybody tell me why I am getting a null pointer exception at that point?

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Omar N
  • 1,720
  • 2
  • 21
  • 33

3 Answers3

2

Because the Integer wrapper type is nullable and in your queue you have a null Integer that you then try to cast as int primitive type ...

Try to put a conditional check verifying that the element is not null like this :

while(it.hasNext()) {
          Integer e = it.next();
          if(e != null)
            assertEquals(i, (int)e );
          i++;
        }
aleroot
  • 71,077
  • 30
  • 176
  • 213
  • I see. This is because there are two null "dummy" nodes at both ends of the of the deque, right? – Omar N Oct 30 '15 at 14:22
  • Yes, but you should check for them in the iterator, not in your test code. Your iterator should not return a `null` item if such an item can not be added to the collection in the first place. – Mad Physicist Oct 30 '15 at 14:23
1

Start off by looking at the termination condition for the loop:

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

This means that the last time it runs, it will return null, since it only checks that the current element, not the next element, is non-null.

So your code becomes something like this:

Integer it_next = null;
assertEquals(i, (int)it_next);

And that cast to int is what's throwing the exception. If you look at the rules for how unboxing works, you can figure out why:

If r is a reference of type Integer, then unboxing conversion converts r into r.intValue()

So your code becomes similar to

((Integer)null).intValue();

which is a method call on a null value, causing the exception.

Presumably, the fix you want for this is to not return true in hasNext if the next value is null. Something like this:

public boolean hasNext(){
    return current != null && current.next != null;
}
resueman
  • 10,572
  • 10
  • 31
  • 45
1

Given the incomplete code that you posted, it appears that there is a marker for the end of the deque called last, and that its item is most likely null.

Correct your iterator to check for last in hasNext():

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

The check for null has been retained for safety. It is probably not necessary.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
  • Well, there are two dummy nodes on both ends of the deque, both of which are null. They are called `first` and `last`. Since `last = null`, wouldn't the check for `current != null` in `hasNext()` suffice? – Omar N Oct 30 '15 at 14:30
  • From the code you posted, `last` is by no means `null` (e.g., the line `ptr.prev.next = node;`, after setting `ptr = last;` ). `last.next` is probably `null` though, and `last.item` is too. – Mad Physicist Oct 30 '15 at 14:33