Ricerca…


introduzione

java.util.Iterator è l'interfaccia standard Java SE per oggetti che implementano il modello di progettazione Iterator. L'interfaccia java.lang.Iterable è per gli oggetti che possono fornire un iteratore.

Osservazioni

È possibile iterare su un array usando il ciclo for -each, sebbene gli array java non implementino Iterable; l'iterazione viene eseguita da JVM utilizzando un indice non accessibile in background.

Uso di loop Iterable in for

Le classi che implementano l'interfaccia Iterable<> possono essere utilizzate in cicli for . Questo è in realtà solo zucchero sintattico per ottenere un iteratore dall'oggetto e utilizzarlo per ottenere tutti gli elementi in sequenza; rende il codice più chiaro, più veloce da scrivere e meno incline agli errori.

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);
        }
    }
}

Utilizzando l'iteratore raw

L'uso del ciclo foreach (o "extended for loop") è semplice, a volte è utile utilizzare direttamente l'iteratore. Ad esempio, se desideri generare un gruppo di valori separati da virgola, ma non vuoi che l'ultimo elemento abbia una virgola:

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(",");
    }
}

Questo è molto più facile e più chiaro di avere una variabile isLastEntry o fare calcoli con l'indice di loop.

Crea il tuo Iterable.

Per creare il tuo Iterable come con qualsiasi interfaccia, devi semplicemente implementare i metodi astratti nell'interfaccia. Per Iterable c'è solo uno che è chiamato iterator() . Ma il suo tipo di ritorno Iterator è di per sé un'interfaccia con tre metodi astratti. Puoi restituire un iteratore associato ad alcune raccolte o creare la tua implementazione personalizzata:

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");
            }
        };
    }
}

Usare:

public static void main(String[] args) {
    for(char c : new Alphabet()) {
        System.out.println("c = " + c);
    }
}

Il nuovo Iterator dovrebbe avere uno stato che punta al primo elemento, ogni chiamata al successivo aggiorna il suo stato in modo che punti a quello successivo. hasNext() controlla se l'iteratore è alla fine. Se l'iteratore fosse collegato a una raccolta modificabile, il metodo remove() facoltativo dell'iteratore potrebbe essere implementato per rimuovere l'elemento attualmente indirizzato dalla raccolta sottostante.

Rimozione di elementi mediante un iteratore

Il metodo Iterator.remove() è un metodo facoltativo che rimuove l'elemento restituito dalla precedente chiamata a Iterator.next() . Ad esempio, il codice seguente popola un elenco di stringhe e quindi rimuove tutte le stringhe vuote.

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());

Produzione :

Old Size : 5
New Size : 3

Nota che il codice sopra è il modo sicuro per rimuovere elementi mentre si itera una raccolta tipica. Se invece, provi a rimuovere elementi da una raccolta come questa:

for (String el: names) {
    if (el.equals("")) {
        names.remove(el); // WRONG!
    }
}

una raccolta tipica (come ArrayList ) che fornisce agli iteratori la semantica dell'iteratore di fail veloce genererà una ConcurrentModificationException .

Il metodo remove() può solo chiamare (una volta) dopo una chiamata next() . Se viene chiamato prima di chiamare next() o se viene chiamato due volte dopo una chiamata next() , allora la chiamata remove() genererà un IllegalStateException .

L'operazione di remove è descritta come un'operazione opzionale ; cioè non tutti gli iteratori lo permetteranno. Esempi in cui non è supportato includono iteratori per raccolte immutabili, viste di sola lettura di raccolte o raccolte di dimensioni fisse. Se remove() viene chiamato quando l'iteratore non supporta la rimozione, genererà un UnsupportedOperationException .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow