1.4-Software-Development-Principles

Iterable (and Iterator)

Introduction

The simplest interface to represent a list is the Iterable interface. This interface allows you to iterate over the various elements within the list. An additional bonus is that when this interface is implemented, you may use an enhanced for-loop to iterate over the elements in your very own LinkedList.

The Iterable interface looks like this*:

public interface Iterable<T> {
    Iterator<T> iterator();
}

*There are two more methods, but you only need to override this one. (Did we tell you about default implementations yet? Feel free to ignore this tid-bit.)

The one method of Iterable returns a specific implementation of Iterator. Which defines two methods:

public interface Iterator<T> {
    T next();
    boolean hasNext();
}

You could write a normal loop using an iterator:

for (Iterator<T> i=list.iterator(); i.hasNext(); ) {
    T current = i.next();    	
}

But once again, it makes more sense to simply do:

for (T current:list) {
	
}

Note: Just to make it clear:

Assignment

Step 1: Make your list implement the Iterable interface.

Add the interface to the class and start writing the iterable() method. You will notice that you for now have no idea what you should return. Implement the method by simply returning null.

Step 2: Add an internal class that implements the Iterator interface.

At the end of the class body, but still within the body of the class declare a new class. Call it MyIterator if you want.

Note: We expect that your root node is declared as private. This new internal class is an integral part of the entire class and therefore has access to its private fields.

The point of your Iterator is to traverse over each node of your linked list.

Conclusion

Now that your very own LinkedList class implements Iterable confirm its content with a dedicated unittest. I find the following methods handy, feel free to “borrow” them.

@Test
public void GivenMyOwnList_WhenIterating_AllValuesMatch() {
    // This is an example
    assertContent(myOwnList, "Item 1", "Item 2", "Item 3", "Item 4");	
}

public static <Q> void assertContent(Iterable<Q> iterable, Q... values) {
    assertNotNull(iterable);
    assertContent(iterable.iterator(), values);
    // Or use the built in:
    assertIterableEquals(iterable, values);
}

public static <Q> void assertContent(Iterator<Q> iterator, Q... values) {
    for (Q value:values) {
        assertTrue(iterator.hasNext());
        Q actual = iterator.next();
        assertEquals(value, actual);
    }
    assertFalse(iterator.hasNext());
}