– Szia Amigo!

– Szia, Ellie!

– Ma az iterátorokról szeretnék mesélni.

"Az iterátorokat gyakorlatilag a gyűjteményekkel egy időben találták ki. A gyűjtemények fő célja az elemek tárolása, az iterátor fő célja pedig az, hogy ezeket az elemeket egyenként lekérje."

– Mi olyan nehéz egy elemkészlet beszerzésében?

"Először is, egyes gyűjteményekben, például a készletben az elemeknek nincs meghatározott sorrendje, és/vagy a sorrend folyamatosan változik."

"Másodszor, egyes adatstruktúrák nagyon összetett módon tárolhatják az objektumokat: különböző csoportokban, listákban stb. Más szóval, az összes elemet sorrendben kiosztani nem triviális feladat lenne."

"Harmadszor, a gyűjtemények általában változnak. Tegyük fel, hogy úgy dönt, hogy egy gyűjtemény teljes tartalmát megjeleníti, de a kimenet kellős közepén a JVM egy másik szálra vált, amely a gyűjtemény elemeinek felét lecseréli. Így a kimenet helyett azt kapja, hogy ki tudja mit."

"Hmm..."

"De! Pontosan ilyen problémákat tud megoldani egy iterátor. Az iterátor egy speciális objektum a gyűjteményben, amely egyrészt hozzáfér az összes privát adatához, és ismeri a belső szerkezetét, másrészt , megvalósítja a nyilvános Iterator felületet, amely lehetővé teszi, hogy mindenki tudja, hogyan kell vele dolgozni. "

"Néhány iterátor rendelkezik egy belső tömbbel, amelybe a gyűjtemény összes eleme az iterátor létrehozásakor másolódik. Ez biztosítja, hogy a gyűjtemény későbbi módosításai ne befolyásolják az elemek számát vagy sorrendjét."

"Szerintem találkoztál ezzel, amikor mindegyiknél dolgozol . Nem lehet egyszerre hurkolni egy gyűjteményt, és eltávolítani belőle elemeket. Ez pontosan az iterátor működése miatt van így."

"A párhuzamossági könyvtárhoz hozzáadott új gyűjteményekben az iterátort átdolgozták a probléma kiküszöbölése érdekében."

– Hadd emlékeztesselek az iterátor működésére.

"A Java speciális Iterator felülettel rendelkezik. Íme a módszerei:

Az Iterator<E> interfész módszerei Leírás
boolean hasNext() Ellenőrzi, hogy vannak-e további elemek
E next() Visszaadja az aktuális elemet, és a következőre lép.
void remove() Eltávolítja az aktuális elemet

"Egy iterátor lehetővé teszi a gyűjtemény összes elemének egymás utáni megszerzését. Logikusabb az iterátort úgy tekinteni, mint valami InputStream-et – az összes adatot tartalmazza, de az a feladata, hogy szekvenciálisan kiadja azokat."

"A   következő () metódus a gyűjtemény következő elemét adja vissza."

"A hasNext () módszerrel ellenőrizhető, hogy vannak-e további elemek."

"És eltávolítás () eltávolítja az aktuális elemet."

"Bármi kérdés?"

"Miért van a metódusoknak ilyen furcsa neve? Miért nem az isEmpty() és a getNextElement()?"

– Nem lenne több értelme?

"Sokkal értelmesebb lenne, de a nevek a C++ nyelvből származtak, ahol korábban megjelentek az iterátorok."

– Értem. Folytassuk.

"Az iterátoron kívül létezik az Iterable felület is, amelyet minden iterátort támogató gyűjteménynek implementálnia kell. Egyetlen metódusa van:"

Az Iterable<T> interfész módszerei Leírás
Iterator<T>iterator() Egy iterátor objektumot ad vissza

"Ezt a módszert bármely gyűjteményben használhatja, hogy egy iterátor objektumot végigjárjon az elemein. Menjünk végig a TreeSet összes elemén :"

Példa
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

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

"Egy ilyen iterátor használata nem túl kényelmes – túl sok a felesleges és nyilvánvaló kód. A helyzet egyszerűbbé vált, amikor a for-each ciklus megjelent a Java-ban."

"Most ez a kód sokkal kompaktabb és olvashatóbb:"

Előtt Után
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);
}

"Ez ugyanaz a kód! Mindkét esetben az iterátort használják."

"Csak arról van szó, hogy a használata el van rejtve a for-each ciklusban. Vegye figyelembe, hogy a jobb oldali kódban egyáltalán nincs piros szöveg. Az iterátor használata teljesen rejtett."

"A for-each ciklus használható minden olyan objektumhoz, amely támogatja az iterátorokat. Más szóval, megírhatja saját osztályát, hozzáadhatja az iterátor () metódust, és használhatja az objektumokat egy for-each konstrukcióban."

"Hűha! Természetesen nem szívesen írok saját gyűjteményeimet és iterátoraimat, de a kilátás még mindig csábító. Megjegyzem."

Ezenkívül van egy másik népszerű iterátortípus, amely még saját felülettel is rendelkezik. Egy listák iterátoráról beszélek, azaz a ListIteratorról .

"Feldolgozásuktól függetlenül a listák megtartják az elemek sorrendjét, ami egy kicsit kényelmesebbé teszi velük az iterátoron keresztüli munkát."

"Íme a ListIterator <E> felületének metódusai :"

Módszer Leírás
boolean hasNext() Ellenőrzi, hogy van-e további elem.
E next() A következő elemet adja vissza.
int nextIndex() A következő elem indexét adja vissza
void set(E e) Módosítja az aktuális elem értékét
boolean hasPrevious() Ellenőrzi, hogy vannak-e mögötte elemek.
E previous() Az előző elemet adja vissza
int previousIndex() Az előző elem indexét adja vissza
void remove() Eltávolítja az aktuális elemet
void add(E e) Hozzáad egy elemet a lista végéhez.

"Más szóval, itt előre és hátra is haladhatunk. És van még egy-két apró tulajdonság."

"Nos, ez érdekes dolog. Hol használják?"

"Tegyük fel, hogy előre-hátra szeretne mozogni egy linkelt listán. A get művelet meglehetősen lassú lesz, de a next() művelet nagyon gyors lesz."

"Hmm. Meggyőztél. Szem előtt tartom."

– Köszönöm, Ellie!