1. Historia pojawienia się iteratora
Poznałeś już wielu HashSet
. A jeśli naprawdę się tym zajmowałeś, a nie tylko wykładałeś, powinieneś był się zastanawiać:
A jak wyświetlić listę wszystkich elementów zestawu HashSet na ekranie? get()
W końcu na wielu nie ma metod set()
!
I HashSet
nie jest sam w swoim problemie. Oprócz HashSet
, istnieje wiele innych kolekcji, dla których nie można uzyskać elementu po numerze, ponieważ nie ma jasnej kolejności elementów.
Programiści wymyślili kiedyś wiele złożonych struktur danych, takich jak wykres, drzewo. Lub na przykład lista list.
Wiele kontenerów zmienia kolejność swoich elementów po dodaniu nowych elementów lub usunięciu istniejących elementów. Na przykład istnieje lista, która przechowuje elementy w posortowanej kolejności, a kiedy dodawany jest nowy element, prawie zawsze jest on wstawiany na środku listy.
Otrzymujemy więc sytuację, że istnieje kontener zawierający elementy, same elementy również istnieją, ale nie ma ustalonej kolejności.
Ale powiedzmy, że chcemy skopiować wszystkie elementy z takiej kolekcji do tablicy lub listy. Musimy zdobyć wszystkie elementy. Nie dbamy o to, w jakiej kolejności je obchodzimy, najważniejsze, aby się nie powtarzać. Jak możemy to zrobić?
2. Iterator kolekcji
Jako rozwiązanie powyższego problemu zaproponowano rozwiązanie - iterator .
Iterator to specjalny obiekt kolekcji, który pomaga iterować po wszystkich elementach kolekcji i nie powtarzać się.
Możesz uzyskać iterator z dowolnej kolekcji za pomocą kodu:
Iterator<Тип> it = Nazwa.iterator();
Gdzie Nazwa
to nazwa zmiennej kolekcji, Тип
to typ elementów kolekcji. iterator()
jest metodą zbierania. it
jest nazwą zmiennej obiektowej iteratora.
Obiekt iteratora ma 3 metody:
metoda | Opis |
---|---|
|
Zwraca następny element kolekcji |
|
Sprawdza, czy istnieją elementy, które nie zostały jeszcze przekazane |
|
Usuwa bieżący element kolekcji |
Te metody są nieco podobne do metod klasy Scanner: nextInt()
i hasNextInt()
.
Metoda next()
zwraca kolejny element kolekcji, z której otrzymaliśmy iterator.
Metoda hasNext()
sprawdza, czy w kolekcji jest więcej elementów, których iterator nie zwrócił.
Oto jak możesz wyświetlić wszystkie elementy zestawu HashSet
:
Kod | Notatki |
---|---|
|
Tworzymy obiekt typu HashSet , który przechowuje elementy typu String . Dodajemy set pozdrowienia w różnych językach. Otrzymujemy obiekt iteratora ze zbioru set . Dopóki są jeszcze elementy Zdobądź następny element Wyświetl element na ekranie |
3. Pętlafor-each
Główną wadą iteratora jest to, że używanie go do kodu jest jeszcze bardziej kłopotliwe niż użycie pętli for
.
Wyświetlmy listę za pomocą pętli for
i iteratora dla porównania:
iterator | dla pętli |
---|---|
|
|
Tak, ArrayList
dużo lepiej jest poruszać się po elementach listy za pomocą pętli - wszystko jest krótsze.
Jednak programiści Javy postanowili znowu dać nam cukier. I na szczęście dla nas znowu był to cukier składniowy .
Dodali nowy rodzaj pętli do Javy i nazwali ją for-each
. Oto jak to ogólnie wygląda:
for(Тип Nazwa:коллекция)
Gdzie коллекция
jest nazwą zmiennej kolekcji, Тип
jest typem elementów kolekcji i Nazwa
jest nazwą zmiennej, która pobiera następną wartość z kolekcji w każdej iteracji pętli.
Ta pętla przechodzi przez wszystkie elementy kolekcji za pomocą ukrytego iteratora. Oto jak to faktycznie działa:
dla każdej pętli | Co widzi kompilator: Pętla iteratora |
---|---|
|
|
Gdy kompilator napotka pętlę w twoim kodzie for-each
, po prostu zastąpi ją kodem po prawej stronie: doda gettera iteratora i wszelkie brakujące wywołania metod.
Programiści bardzo lubią pętle for-each
i prawie zawsze używają ich, gdy muszą przejrzeć wszystkie elementy kolekcji.
Nawet przeglądanie listy ArrayList
za pomocą pętli for-each
wygląda krócej:
dla każdej pętli | dla pętli |
---|---|
|
|
4. Usuwanie elementu w pętlifor-each
Cykl for-each
ma jeden minus: nie wie, jak poprawnie usunąć elementy. Jeśli napiszesz taki kod, pojawi się błąd.
Kod | Notatka |
---|---|
|
Podczas usuwania wystąpi błąd! |
To bardzo piękny i zrozumiały kod, ale nie zadziała.
Nie możesz modyfikować kolekcji podczas iteracji za pomocą iteratora.
Istnieją trzy sposoby obejścia tego ograniczenia.
1 Korzystanie z innego cyklu
Jeśli iterujesz nad kolekcją ArrayList
, możesz użyć zwykłej pętli licznika i
.
Kod |
---|
|
Jednak ta opcja nie jest odpowiednia dla kolekcji HashSet
iHashMap
2 Jawne użycie iteratora
Możesz jawnie użyć iteratora i użyć jego remove()
.
wersja robocza | Opcja niedziałająca |
---|---|
|
|
Zauważ, że remove()
wywołujemy metodę na obiekcie iteratora! Iterator będzie „wiedział”, że element został usunięty i będzie w stanie odpowiednio obsłużyć tę sytuację.
3 Korzystanie z kopii kolekcji
Możesz także utworzyć kopię kolekcji i użyć for-each
kolekcji-kopiowania w pętli oraz usunąć elementy z oryginalnej kolekcji.
Kod | Notatka |
---|---|
|
Tworzenie kopii kolekcji jest bardzo proste.Pętla wykorzystuje iterator kolekcji kopii. Elementy są usuwane z kolekcji list . |
Kopia kolekcji tworzona jest dość szybko: elementy nie są duplikowane podczas kopiowania kolekcji, nowa kolekcja będzie zawierała linki do tych samych elementów, co stara.
GO TO FULL VERSION