1. Context despre cum au apărut iteratorii
Ești deja familiarizat cu HashSet
. Dacă ai investigat cu adevărat, dincolo de doar citirea unei lecții, atunci ar fi trebuit să pui această întrebare:
Cum afișez pe ecran o listă cu toate elementele HashSet? La urma urmei, interfața nu are get()
și set()
metode!
Și HashSet
nu este singurul în această limitare. Pe lângă HashSet
, există multe alte colecții care nu permit recuperarea elementelor prin index, deoarece elementele nu au o ordine definită.
De-a lungul anilor, programatorii au inventat o mulțime de structuri complexe de date, cum ar fi grafice și arbori. Sau liste de liste.
Multe containere își schimbă ordinea elementelor atunci când sunt adăugate elemente noi sau sunt eliminate elementele existente. De exemplu, o listă stochează elemente într-o anumită ordine, iar atunci când este adăugat un element nou, acesta este aproape întotdeauna inserat în mijlocul listei.
Și avem și situații în care există un container care stochează elemente, dar nu într-o ordine fixă.
Acum să presupunem că vrem să copiem toate elementele dintr-o astfel de colecție într-o matrice sau listă. Trebuie să obținem toate elementele. Nu ne pasă de ordinea în care repetăm elementele - important este să nu repetăm aceleași elemente de mai multe ori. Cum facem asta?
2. Iterator pentru o colecție
Iteratorii au fost propuși ca soluție la problema de mai sus.
Un iterator este un obiect special asociat cu o colecție, care ajută la traversarea tuturor elementelor colecției fără a repeta niciuna.
Puteți folosi următorul cod pentru a obține un iterator pentru orice colecție:
Iterator<Type> it = name.iterator();
Unde name
este numele variabilei colecției, Type
este tipul elementelor colecției, iterator()
este una dintre metodele colecției și it
este numele variabilei iteratorului.
Un obiect iterator are 3 metode:
Metodă | Descriere |
---|---|
|
Returnează următorul element din colecție |
|
Verifică dacă există elemente care nu au fost încă traversate |
|
Îndepărtează elementul curent al colecției |
nextInt)
Aceste metode sunt oarecum similare cu metodele și clasele Scanner hasNextInt()
.
Metoda next()
returnează următorul element al colecției din care am obținut iteratorul.
Metoda hasNext()
verifică dacă colecția are elemente suplimentare pe care iteratorul nu le-a returnat încă.
Iată cum să afișați toate elementele unui HashSet
:
Cod | Note |
---|---|
|
Creați un HashSet obiect care stochează String elemente. Adăugăm în set variabilă salutări în diferite limbi. Obțineți un obiect iterator pentru set set. Atâta timp cât mai există elemente Obțineți următorul element Afișați elementul pe ecran |
3. For-each
buclă
Principalul dezavantaj al unui iterator este că codul tău devine mai greoi decât utilizarea unei for
bucle.
Pentru a compara, să afișăm o listă folosind o for
buclă și, de asemenea, folosind un iterator:
Iterator | pentru buclă |
---|---|
|
|
Da, este mult mai bine să traversați elementele unei ArrayList
bucle folosind o buclă - totul se dovedește a fi mai scurt.
Dar creatorii lui Java au decis din nou să toarne niște zahăr peste noi. Din fericire pentru noi, a fost zahăr sintactic .
Au dat Java un nou tip de buclă și l-au numit for-each
buclă. Cam asa arata in general:
for(Type name:collection)
Unde collection
este numele variabilei de colecție, Type
este tipul elementelor din colecție și name
este numele unei variabile care ia următoarea valoare din colecție la fiecare iterație a buclei.
Acest tip de buclă iterează prin toate elementele unei colecții folosind un iterator implicit. Iată cum funcționează de fapt:
Pentru fiecare buclă | Ce vede compilatorul: buclă cu un iterator |
---|---|
|
|
Când compilatorul întâlnește o for-each
buclă în codul dvs., pur și simplu o înlocuiește cu codul din dreapta: adaugă un apel pentru a obține un iterator împreună cu orice alte apeluri de metodă lipsă.
Programatorii iubesc for-each
bucla și aproape întotdeauna o folosesc atunci când trebuie să itereze peste toate elementele unei colecții.
Chiar și repetarea unei ArrayList
liste folosind o for-each
buclă pare mai scurtă:
Pentru fiecare buclă | pentru buclă |
---|---|
|
|
4. Eliminarea unui element dintr-o for-each
buclă
Bucla for-each
are un dezavantaj: nu poate elimina corect elementele. Dacă scrieți astfel de cod, veți primi o eroare.
Cod | Notă |
---|---|
|
Operația de eliminare va genera o eroare! |
Acesta este un cod foarte frumos și de înțeles, dar nu va funcționa.
Nu puteți schimba o colecție în timp ce o parcurgeți cu un iterator.
Există trei moduri de a ocoli această limitare.
1. Folosiți un alt tip de buclă
When traversing an ArrayList collection
, puteți utiliza o buclă obișnuită cu o i
variabilă contor.
Cod |
---|
|
Cu toate acestea, această opțiune nu este potrivită pentru HashSet
și HashMap
colecții
2. Utilizați un iterator explicit
Puteți utiliza un iterator în mod explicit și puteți apela remove()
metoda acestuia.
Versiune care funcționează | Versiune care nu merge |
---|---|
|
|
Rețineți că numim remove()
metoda pe obiectul iterator! Iteratorul este conștient de faptul că elementul a fost eliminat și poate gestiona situația corect.
3. Folosiți o copie a colecției
De asemenea, puteți crea o copie a colecției și apoi utilizați copia într-o for-each
buclă și ștergeți elemente din colecția originală.
Cod | Notă |
---|---|
|
Crearea unei copii a unei colecții este foarte ușoară. Bucla folosește iteratorul pentru copia colecției. Elementele sunt eliminate din list colecție. |
Colecția este copiată destul de repede, deoarece elementele în sine nu sunt duplicate. În schimb, noua colecție stochează referințe la elementele care există deja în vechea colecție.
GO TO FULL VERSION