"Hej, Amigo!"

"Hej Ellie!"

"Idag vill jag berätta om iteratorer."

"Iteratorer uppfanns praktiskt taget samtidigt som samlingar. Huvudsyftet med samlingar är att lagra element, och huvudsyftet med en iterator är att hämta dessa element en efter en."

"Vad är det som är så svårt med att få en uppsättning element?"

"För det första har elementen i vissa samlingar, som Set, inte en etablerad ordning och/eller ordningen ändras konstant."

"För det andra kan vissa datastrukturer lagra objekt på ett mycket komplext sätt: i olika grupper, listor etc. Med andra ord skulle det vara en icke-trivial uppgift att dela ut alla element i ordning."

"För det tredje tenderar samlingar att förändras. Anta att du bestämmer dig för att visa hela innehållet i en samling, men mitt i utgången växlar JVM till en annan tråd som ersätter hälften av samlingens element. Så istället för utgången får du vem vet vad."

"Hmm..."

"Men! Det är just den sortens problem som en iterator kan lösa. En iterator är ett speciellt objekt inom en samling som å ena sidan har tillgång till alla sina privata data och känner till sin interna struktur, och å andra sidan , implementerar det offentliga Iterator-gränssnittet, som låter alla veta hur man arbetar med det. "

"Vissa iteratorer har en intern array till vilken alla element i samlingen kopieras när iteratorn skapas. Detta säkerställer att eventuella efterföljande ändringar av samlingen inte påverkar antalet eller ordningen på elementen."

"Jag tror att du har stött på detta när du arbetar med för varje . Du kan inte samtidigt loopa över en samling och ta bort element från den. Allt detta är just på grund av hur en iterator fungerar."

"I de nya samlingarna som läggs till samtidighetsbiblioteket är iteratorn omarbetad för att eliminera detta problem."

"Låt mig påminna dig om hur en iterator fungerar."

"Java har ett speciellt Iterator-gränssnitt. Här är dess metoder:"

Metoder för Iterator<E>-gränssnittet Beskrivning
boolean hasNext() Kontrollerar om det finns fler element
E next() Returnerar det aktuella elementet och flyttar till nästa.
void remove() Tar bort det aktuella elementet

"En iterator låter dig successivt få alla element i en samling. Det är mer logiskt att tänka på en iterator som något som en InputStream - den har all data, men dess uppgift är att mata ut den sekventiellt."

"   Nästa ()-metoden returnerar nästa element i samlingen."

" Metoden hasNext () används för att kontrollera om det finns några fler element."

"Och remove () tar bort det aktuella elementet."

"Några frågor?"

"Varför har metoderna så konstiga namn? Varför inte isEmpty() och getNextElement()?"

"Skulle inte det vara mer vettigt?"

"Det skulle vara mer vettigt, men namnen kom från språket C++, där iteratorer förekom tidigare."

"Jag förstår. Låt oss fortsätta."

"Förutom en iterator finns det också Iterable-gränssnittet, som måste implementeras av alla samlingar som stöder iteratorer. Det har en enda metod:"

Metoder för Iterable<T>-gränssnittet Beskrivning
Iterator<T>iterator() Returnerar ett iteratorobjekt

"Du kan använda den här metoden på vilken samling som helst för att få ett iteratorobjekt att gå igenom dess element. Låt oss gå över alla element i en TreeSet :"

Exempel
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}

"Att använda en iterator som denna är inte särskilt bekvämt - det finns för mycket överflödig och uppenbar kod. Situationen blev enklare när för- varje- slingan dök upp i Java."

"Nu är den här koden mycket mer kompakt och läsbar:"

Innan Efter
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}
TreeSet<String> set = new TreeSet<String>();

for(String item : set)
{
 System.out.println(item);
}

"Detta är samma kod! Iteratorn används i båda fallen."

"Det är bara det att dess användning är gömd i för varje loop. Observera att koden till höger inte har någon röd text alls. Användningen av iteratorn är helt dold."

"En för varje slinga kan användas för alla objekt som stöder iteratorer. Med andra ord kan du skriva din egen klass, lägga till metoden iterator () till den och använda dess objekt i en för varje konstruktion."

"Wow! Naturligtvis är jag inte sugen på att skriva mina egna samlingar och iteratorer, men utsikten är fortfarande frestande. Jag ska anteckna det."

Dessutom finns det en annan populär typ av iterator som till och med har sitt eget gränssnitt. Jag pratar om en iterator för listor, dvs ListIterator .

"Oavsett deras implementering bibehåller listor ordningen på elementen, vilket gör det lite bekvämare att arbeta med dem genom en iterator."

"Här är metoderna för ListIterator <E>-gränssnittet:"

Metod Beskrivning
boolean hasNext() Kollar om det finns fler element framöver.
E next() Returnerar nästa element.
int nextIndex() Returnerar indexet för nästa element
void set(E e) Ändrar värdet på det aktuella elementet
boolean hasPrevious() Kontrollerar om det finns några element bakom.
E previous() Returnerar föregående element
int previousIndex() Returnerar indexet för föregående element
void remove() Tar bort det aktuella elementet
void add(E e) Lägger till ett element i slutet av listan.

"Med andra ord, här kan vi röra oss både framåt och bakåt. Och det finns ett par andra små finesser."

"Tja, det är intressanta saker. Var används det?"

"Anta att du vill flytta fram och tillbaka på en länkad lista. Get-operationen kommer att vara ganska långsam, men nästa()-operationen kommer att vara mycket snabb."

"Hmm. Du övertygade mig. Jag ska ha det i åtanke."

"Tack, Ellie!"