...
Iterasjon med for-each-løkke | Iterasjon med eksplisitt Iterator |
---|
Code Block |
---|
| // gå gjennom stringListe
for (String s : stringListe) {
// gjør noe med s her
...
} |
| Code Block |
---|
| // få en iterator fra stringListe
Iterator<String> stringIterator = stringListe.iterator();
// bruk hasNext og next for å gå gjennom lista
while (stringIterator.hasNext()) {
String s : stringIterator.next();
// gjør noe med s her
...
} |
|
...
PlantUML Macro |
---|
interface "Iterable<T>" as iterable {
Iterator<T> iterator()
}
interface "Collection<T>" as collection
interface "List<T>" as list
class "ArrayList<T>" as arraylist
class "LinkedList<T>" as linkedlist
iterable <|-downright- collection
collection <|-downright- list
list <|.down. arraylist
list <|.down. linkedlist |
En Iterator for en Library-klasse kan se slik ut:
Code Block |
---|
|
// OBS: Merk at metodene i denne klassen er uferdige. Logikken i hver metode vil avhenge av hvordan Library-klassen er.
import java.util.Iterator;
public class LibraryIterator implements Iterator<Book> {
private Library library;
// Eventuelle andre tilstander for å holde styr på iterasjonen
public LibraryIterator(Library library) {
this.library = library;
// Sett eventuelle andre tilstander
}
public boolean hasNext() {
boolean hasNext = false;
// Kode for å sjekke om Library har flere Book-objekter
return hasNext;
}
public Book next() {
// Returner neste Book i Library
return book;
}
public void remove() {
// Kode for å fjerne sist returnerte bok eller la stå tom
}
} |
Iterable-grensesnittet
Når et objekt implementerer Iterable-grensesnittet sikrer man at det er mulig å iterere over objektet. Et Iterable<type>-objekt trenger kun å implementere én metode:
- Iterator<type> iterator() - returnerer en Iterator<type> for å iterere over objektet.
Under følger et eksempel på Library-klassen fra eksempelet over, som implementerer Iterable<Book>:
...
Som vi ser er også Iterable spesialisert til element-typen. Så dersom en har en List<String> så har en implisitt en Iterable<String>, som har en iterator()-metode som returnerer en Iterator<String>, som har en next()-metode som returnerer en String.
Siden Iterable er et vanlig grensesnitt, så kan våre egne klasser utvide den og utnytte den kompakte for-each-syntaksen. Anta f.eks. at en har en Library-klasse, som bruker en ArrayList til å holde Book-objekter. Kode for en slik klasse er vist under til venstre. Dersom denne klassen også implementerer Iterable<Book> så kan en bruke for-each-løkka for å gå gjennom Book-objektene i et Library-objekt. Koden for denne utvidete Library-klassen er vist i midten og for-each-løkka er vist til høyre.
...
Klasse som bruker ArrayList | Klasse som også implementerer Iterable | for-each-løkke |
---|
Code Block |
---|
| public class Library {
private Collection<Book> books = new ArrayList<Book>();
public void addBook(Book book) {
books.add(book);
}
public void removeBook(Book book) {
books.remove(book);
}
} |
| |
public class Library implements Iterable<Book> {
|
|
...
...
...
...
...
her ...
// fra Iterable<Book>
public Iterator<Book> iterator() {
return |
|
...
I mange tilfeller bruker vi ArrayList eller andre typer lister som allerede implementerer Iterator-grensesnittet. Dette kan vi utnytte i nye klasser:
Code Block |
---|
|
import java.util.Iterator;
public class Library implements Iterable<Book> {
private ArrayList<Book> books;
// Andre tilstander og metoder i klassen er ikke definert her
public Iterator<Book> iterator() {
// Returnerer ArrayList's iterator
return books.iterator();
}
} |
Fordeler med Iterator / Iterable
Når et objekt implementerer Iterable<type> kan man bruke for-løkker av denne typen:
...
...
Code Block |
---|
// lag en Library-instans
Library library = new Library();
// legg til noen bøker
library.addBook(new Book(...));
library.addBook(new Book(...));
// gå gjennom bøkene
for (Book book : library |
|
...
...
...
...
...