Laura Pierce Laura Pierce - 2 months ago 16
Java Question

Why isn't my iterator working?

For a class assignment I have to implement my own iterator from scratch. The iterator is iterating through a linked list of nodes. All of my test cases that use the iterator are failing and I can't tell what is wrong with it.

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

class LinkedNodeIterator<E> implements Iterator<E> {
LinkedNode<E> headNode;
LinkedNode<E> curr;


// Constructors
public LinkedNodeIterator(LinkedNode<E> head) {
headNode = head;
curr = headNode;
}

@Override
public boolean hasNext() {
if(headNode == null)
return false;
if(curr.getNext() == null)
return false;
return true;
}

@Override
public E next() {
if(curr.getNext() == null || curr == null)
throw new NoSuchElementException();
LinkedNode<E> save = curr;
curr = curr.getNext();
return save.getData();

}


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


Some test cases that fail (they all return count = 0):

public class PublicLinkedSetTest {
Set<String> set0;
Set<String> set1;
Set<String> set2;
Set<String> set3;
Set<String> set4;


@Before
public void before() {
set0 = new LinkedSet<String>();
set1 = new LinkedSet<String>();
for (String e : new String[]{"c", "a", "d", "b", "e"}) {
set1 = set1.adjoin(e);
}
set2 = new LinkedSet<String>();
for (String e : new String[]{"b", "d", "a", "e", "c"}) {
set2 = set2.adjoin(e);
}
set3 = new LinkedSet<String>();
for (String e : new String[]{"a", "d", "b"}) {
set3 = set3.adjoin(e);
}
set4 = new LinkedSet<String>();
for (String e : new String[]{"x", "y", "z", "a", "b", "d"}) {
set4 = set4.adjoin(e);
}
}

public void testIterator1() {
int count = 0;
for (String e : set1) {
count += 1;
}
assertEquals(5, count);
}

@Test

public void testIterator2() {
int count = 0;
for (String e : set2) {
count += 1;
}
assertEquals(5, count);
}

@Test

public void testIterator3() {
int count = 0;
for (String e : set3) {
count++;
}
assertEquals(3, count);
}


Here is the code for my LinkedSet

import java.util.Iterator;

public class LinkedSet<E> implements Set<E> {
private LinkedNode<E> head = null;
private LinkedNode<E> link;

// Constructors
public LinkedSet() {
}

public LinkedSet(E e) {
this.head = new LinkedNode<E>(e, null);
}

private LinkedSet(LinkedNode<E> header) {
header = head;

}

@Override
public int size() {
int count = 0;
for(E e : this){
count++;}
return count;
}

@Override
public boolean isEmpty() {
for(E e : this){
if(e != null)
return false;
}
return true;
}

@Override
public LinkedNodeIterator<E> iterator() {
return new LinkedNodeIterator<E>(this.head);
}

@Override
public boolean contains(Object o) {
for(E e : this){
if(e == o)
return true;
}
return false;
}

@Override
public boolean isSubset(Set<E> that) {
that = new LinkedSet<E>();
if(this.size()>that.size())
return false;
for(E e : this){
if(that.contains(e) == false)
return false;
}
return true;
}

@Override
public boolean isSuperset(Set<E> that) {
that = new LinkedSet<E>();
if(this.isSubset(that))
return true;
else
return false;
}

@Override
public Set<E> adjoin(E e) {
boolean alwaysEqual = true;
if(this.head == null)
return this;
for(E t : this){
if(t != e)
alwaysEqual = false;}
if(alwaysEqual == true)
return this;
LinkedNode<E> temp = this.head;
LinkedNode<E> newNode = new LinkedNode<E>(e, temp);
LinkedSet<E> newSet = new LinkedSet<E>(newNode);
Set<E> otherSet = newSet;

return otherSet;
}

@Override
public Set<E> union(Set<E> that) {
Set<E> thisSet = this;
for(E e : that){
if(!this.contains(e))
thisSet = thisSet.adjoin(e);

}

return thisSet;
}

@Override
public Set<E> intersect(Set<E> that) {
LinkedSet<E> newSet = null;
Set<E> otherNewSet = newSet;
for(E e : that){
if(this.contains(e)){
if(otherNewSet == null){
LinkedNode<E> newNode = new LinkedNode<E>(e, null);
otherNewSet = new LinkedSet<E>(newNode);
}
else{

otherNewSet = otherNewSet.adjoin(e);
}

}
}

return otherNewSet;
}

@Override
public Set<E> subtract(Set<E> that) {
LinkedSet<E> newSet = null;
Set<E> otherNewSet = newSet;
for(E e : that){
if(!this.contains(e)){
if(otherNewSet == null){
LinkedNode<E> newNode = new LinkedNode<E>(e, null);
otherNewSet = new LinkedSet<E>(newNode);
}
else{

otherNewSet = otherNewSet.adjoin(e);
}

}
}

return otherNewSet;
}

@Override
public Set<E> remove(E e) {
LinkedSet<E> newSet = null;
Set<E> otherNewSet = newSet;
if(!this.contains(e))
return this;
else{
for(E t : this){
if(t != e){
if(otherNewSet == null){
LinkedNode<E> newNode = new LinkedNode<E>(e, null);
otherNewSet = new LinkedSet<E>(newNode);
}
}
else{

otherNewSet = otherNewSet.adjoin(e);
}
}
}
return otherNewSet;
}

@Override
@SuppressWarnings("unchecked")
public boolean equals(Object o) {
if (! (o instanceof Set)) {
return false;
}
Set<E> that = (Set<E>)o;
return this.isSubset(that) && that.isSubset(this);
}

@Override
public int hashCode() {
int result = 0;
for (E e : this) {
result += e.hashCode();
}
return result;
}
}

Tim Tim
Answer

The problem isn't your iterator, it's your adjoin method.

When you construct a new LinkedSet like this:

 set1 = new LinkedSet<String>();

It means that you call this constructor:

    // Constructors
    public LinkedSet() {
    }

But that constructor doesn't assign anything to head, so it has its default initial value:

    private LinkedNode<E> head = null;

Since head starts off as null, and isn't ever assigned to, this method never does anything but return this:

@Override
public Set<E> adjoin(E e) {
    boolean alwaysEqual = true;
    if (this.head == null)
        return this;
    for (E t : this) {
        if (t != e)
            alwaysEqual = false;
    }
    if (alwaysEqual == true)
        return this;
    LinkedNode<E> temp = this.head;
    LinkedNode<E> newNode = new LinkedNode<E>(e, temp);
    LinkedSet<E> newSet = new LinkedSet<E>(newNode);
    Set<E> otherSet = newSet;

    return otherSet;
} 

So your iterator isn't iterating over anything, because your set has nothing in it.

Comments