De meest eenvoudige manier om een lijst te representeren is via de Iterable
interface.
Deze interface maakt het mogelijk om te itereren over de verschillende elementen in de lijst.
Een extra bonus is dat wanneer deze interface geimplementeerd is, je gebruikt kunt maken van een enhanced for-loop om door de elementen jouw eigen LinkedList
gaan.
De Iterable
interface ziet er als volgt uit*:
public interface Iterable<T> {
Iterator<T> iterator();
}
*Eigenlijk zijn er nog twee methoden, maar dit is de enige die je moet implementeren. (Hebben we het al gehad over “default” implementaties? Voel je vrij om dit detail te negeren.)
De ene method van Iterable
geeft een specifieke implementatie terug van Iterator
. Deze definieert twee methoden:
public interface Iterator<T> {
T next();
boolean hasNext();
}
Je zou een gewone loop kunnen schrijven door gebruik te maken van die iterator:
for (Iterator<T> i=list.iterator(); i.hasNext(); ) {
T current = i.next();
}
Maar het is natuurlijk veel logischer om gewoon dit te doen:
for (T current:list) {
}
Note: Om het helemaal duidelijk te maken:
Iterable
representeert de gehele lijst.Iterator
beweegt over alle elementen van de lijst.
Iterable
interface implementeerd.Voeg de interface toe aan de klasse en begin met het schrijven van de iterable()
methode. Je zult daar nog niet zo heel veel mee kunnen. Dus geef voorlopig gewoon null
terug.
Iterator
interface gebruikt.Aan het eind van je klasse definitie, maar wel binnen de body van de klasse declareren we een nieuwe classe. Noem hem MyIterator
als je wilt.
Note: We gaan er vanuit dat de referentie naar de root node gedeclareerd is als
private
. Maar omdat deze nieuwe interne klasse een integraal onderdeel is van de lijst klasse heeft hij toegang totprivate
velden.
Het doel van de Iterator
is om over alle nodes van jouw lijst te lopen.
next()
methode geeft dan de waarde van het huidige node en beweegt dan alvast naar de volgende node in de lijst.hasNext()
methode geeft true
terug zolang er een huidige node is.null
waarde terug te geven als next()
wordt aangeroepen of gooi een NoSuchElement
exceptie.Nu dat jouw eigen LinkedList
klasse de Iterable
interface implementeerd, kun je specifieke unittests schrijven. Ik vind de volgende methoden handig, voel je vrij om ze te “lenen”.
@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());
}