Java Language
Iterator en Iterable
Zoeken…
Invoering
java.util.Iterator
is de standaard Java SE-interface voor objecten die het Iterator-ontwerppatroon implementeren. De interface java.lang.Iterable
is voor objecten die een iterator kunnen bieden .
Opmerkingen
Het is mogelijk om over een array te itereren met behulp van de for
-each-lus, hoewel Java-arrays geen Iterable implementeren; itereren wordt gedaan door JVM met behulp van een niet-toegankelijke index op de achtergrond.
Iterable in for loop gebruiken
Klassen die Iterable<>
-interface implementeren, kunnen worden gebruikt for
lussen. Dit is eigenlijk alleen syntactische suiker voor het verkrijgen van een iterator van het object en het gebruiken om alle elementen achter elkaar te krijgen; het maakt code duidelijker, sneller om te schrijven en minder foutgevoelig.
public class UsingIterable {
public static void main(String[] args) {
List<Integer> intList = Arrays.asList(1,2,3,4,5,6,7);
// List extends Collection, Collection extends Iterable
Iterable<Integer> iterable = intList;
// foreach-like loop
for (Integer i: iterable) {
System.out.println(i);
}
// pre java 5 way of iterating loops
for(Iterator<Integer> i = iterable.iterator(); i.hasNext(); ) {
Integer item = i.next();
System.out.println(item);
}
}
}
De onbewerkte iterator gebruiken
Hoewel het gebruik van de foreach-lus (of "extended for-lus") eenvoudig is, is het soms voordelig om de iterator direct te gebruiken. Als u bijvoorbeeld een aantal door komma's gescheiden waarden wilt uitvoeren, maar niet wilt dat het laatste item een komma heeft:
List<String> yourData = //...
Iterator<String> iterator = yourData.iterator();
while (iterator.hasNext()){
// next() "moves" the iterator to the next entry and returns it's value.
String entry = iterator.next();
System.out.print(entry);
if (iterator.hasNext()){
// If the iterator has another element after the current one:
System.out.print(",");
}
}
Dit is veel eenvoudiger en duidelijker dan een variabele isLastEntry
of berekeningen uitvoeren met de isLastEntry
.
Je eigen Iterable maken.
Om uw eigen Iterable te maken, zoals bij elke interface, implementeert u gewoon de abstracte methoden in de interface. Voor Iterable
er maar één die iterator()
. Maar het terugkeertype Iterator
is zelf een interface met drie abstracte methoden. U kunt een iterator retourneren die aan een verzameling is gekoppeld of uw eigen aangepaste implementatie maken:
public static class Alphabet implements Iterable<Character> {
@Override
public Iterator<Character> iterator() {
return new Iterator<Character>() {
char letter = 'a';
@Override
public boolean hasNext() {
return letter <= 'z';
}
@Override
public Character next() {
return letter++;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Doesn't make sense to remove a letter");
}
};
}
}
Gebruiken:
public static void main(String[] args) {
for(char c : new Alphabet()) {
System.out.println("c = " + c);
}
}
De nieuwe Iterator
moet een status hebben die naar het eerste item verwijst, elke aanroep naar de volgende update zijn status zodat deze naar de volgende verwijst. hasNext()
controleert of de iterator aan het einde is. Als de iterator verbonden was met een aanpasbare verzameling, zou de optionele methode remove()
de iterator kunnen worden geïmplementeerd om het item waarnaar momenteel wordt verwezen uit de onderliggende verzameling te verwijderen.
Elementen verwijderen met een iterator
De methode Iterator.remove()
is een optionele methode die het element verwijdert dat wordt geretourneerd door de vorige aanroep naar Iterator.next()
. De volgende code vult bijvoorbeeld een lijst met tekenreeksen en verwijdert vervolgens alle lege tekenreeksen.
List<String> names = new ArrayList<>();
names.add("name 1");
names.add("name 2");
names.add("");
names.add("name 3");
names.add("");
System.out.println("Old Size : " + names.size());
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String el = it.next();
if (el.equals("")) {
it.remove();
}
}
System.out.println("New Size : " + names.size());
Uitgang:
Old Size : 5
New Size : 3
Merk op dat de bovenstaande code de veilige manier is om elementen te verwijderen terwijl een typische verzameling wordt herhaald. Als u in plaats daarvan probeert elementen uit een verzameling als volgt te verwijderen:
for (String el: names) {
if (el.equals("")) {
names.remove(el); // WRONG!
}
}
een typische verzameling (zoals ArrayList
) die iterators voorziet van fail-fast iterator-semantiek zal een ConcurrentModificationException
.
De methode remove()
kan alleen (eenmalig) worden aangeroepen na een next()
-aanroep. Als het wordt aangeroepen voordat next()
wordt aangeroepen of als het twee keer wordt aangeroepen na een next()
aanroep, zal de aanroep remove()
een IllegalStateException
.
De remove
wordt beschreven als een optionele bewerking; dat wil zeggen dat niet alle iterators dit toestaan. Voorbeelden waar dit niet wordt ondersteund, zijn iterators voor onveranderlijke collecties, alleen-lezen weergaven van collecties of collecties met een vast formaat. Als remove()
wordt aangeroepen wanneer de iterator verwijdering niet ondersteunt, wordt een UnsupportedOperationException
.