Sök…


Introduktion

java.util.Iterator är det vanliga Java SE-gränssnittet för objekt som implementerar Iterators designmönster. Gränssnittet java.lang.Iterable är för objekt som kan ge en iterator.

Anmärkningar

Det är möjligt att iterera över en matris med hjälp av- for slingan, även om java-matriser inte implementerar Iterable; iterering görs av JVM med hjälp av ett icke tillgängligt index i bakgrunden.

Använda Iterable in för loop

Klasser som implementerar Iterable<> -gränssnitt kan användas for slingor. Detta är faktiskt bara syntaktiskt socker för att få en iterator från objektet och använda det för att få alla element i följd; det gör koden tydligare, snabbare att skriva slut mindre felutsatt.

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

Använd den råa iteratorn

Även om det är enkelt att använda förhandslingan (eller "utökad för slinga") är det ibland fördelaktigt att använda iteratorn direkt. Om du till exempel vill skriva ut ett antal komma-separerade värden, men inte vill att det sista objektet ska ha kommat:

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

Detta är mycket lättare och tydligare än att ha en variabel isLastEntry eller göra beräkningar med loopindex.

Skapa din egen Iterable.

För att skapa din egen Iterable som med alla gränssnitt implementerar du bara de abstrakta metoderna i gränssnittet. För Iterable finns det bara en som kallas iterator() . Men dess Iterator är i sig ett gränssnitt med tre abstrakta metoder. Du kan returnera en iterator som är associerad med någon samling eller skapa en egen anpassad implementering:

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

Att använda:

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

Den nya Iterator bör ha ett tillstånd som pekar på det första objektet, varje uppmaning till nästa uppdaterar sitt tillstånd för att peka till nästa. hasNext() kontrollerar om iteratorn är i slutet. Om iteratorn var ansluten till en modifierbar samling kan iterators valfria remove() -metod implementeras för att ta bort det objekt som för närvarande pekas på från den underliggande samlingen.

Ta bort element med en iterator

Iterator.remove() är en valfri metod som tar bort elementet som returnerades av det föregående samtalet till Iterator.next() . Till exempel innehåller följande kod en lista med strängar och tar bort alla tomma strängar.

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

Utgång:

Old Size : 5
New Size : 3

Observera att koden ovan är det säkra sättet att ta bort element medan du upprepar en typisk samling. Om du istället försöker ta bort element från en samling som denna:

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

en typisk samling (som ArrayList ) som ger iteratorer med fail-snabb iteratorsemantik kommer att kasta en ConcurrentModificationException .

Metoden remove() kan bara ringas (en gång) efter ett next() samtal next() . Om det anropas innan du ringer next() eller om det kallas två gånger efter ett next() samtal next() , kommer det att remove() -samtalet att kasta en IllegalStateException .

Ta remove operationen beskrivs som en valfri operation; dvs inte alla iteratorer tillåter det. Exempel där det inte stöds inkluderar iteratorer för immutable samlingar, skrivskyddade vyer av samlingar eller samlingar i fast storlek. Om remove() kallas när iteratorn inte stöder borttagning, kommer det att kasta en UnsupportedOperationException .



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow