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 HashSetnu 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 nameeste numele variabilei colecției, Typeeste tipul elementelor colecției, iterator()este una dintre metodele colecției și iteste 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 HashSetobiect care stochează Stringelemente. Adăugăm în setvariabilă salutări în diferite limbi. Obțineți un obiect iterator pentru setset. Atâta timp cât mai există elemente Obțineți următorul element Afișați elementul pe ecran |
3. For-eachbuclă
Principalul dezavantaj al unui iterator este că codul tău devine mai greoi decât utilizarea unei forbucle.
Pentru a compara, să afișăm o listă folosind o forbuclă și, de asemenea, folosind un iterator:
| Iterator | pentru buclă |
|---|---|
|
|
Da, este mult mai bine să traversați elementele unei ArrayListbucle 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-eachbuclă. Cam asa arata in general:
for(Type name:collection)
Unde collectioneste numele variabilei de colecție, Typeeste tipul elementelor din colecție și nameeste 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-eachbuclă î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-eachbucla și aproape întotdeauna o folosesc atunci când trebuie să itereze peste toate elementele unei colecții.
Chiar și repetarea unei ArrayListliste folosind o for-eachbuclă pare mai scurtă:
| Pentru fiecare buclă | pentru buclă |
|---|---|
|
|
4. Eliminarea unui element dintr-o for-eachbuclă
Bucla for-eachare 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 ivariabilă contor.
| Cod |
|---|
|
Cu toate acestea, această opțiune nu este potrivită pentru HashSetși HashMapcolecț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-eachbuclă ș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 listcolecț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