1. Iteratorun yaranma tarixi
Artıq HashSet
çoxluğu ilə tanışsınız. Və əgər həqiqətən onunla məşğul olmuşsunuzsa, yalnız dərsi oxumamısınızsa, bu sualı verməli idiniz:
Bəs, HashSet-in bütün elementlərini ekrana necə çıxarmaq olar? Axı, çoxluqda get()
və set()
metodları yoxdur!
Və HashSet
bu problemi ilə tək deyil. HashSet
-dən başqa, hələ bir çox müxtəlif kolleksiyalar var, hansı ki, elementi nömrə üzrə əldə etmək mümkün deyil, çünki elementlərin dəqiq sıralaması yoxdur.
Proqramçılar bir vaxtlar qraf, ağac kimi bir çox çətin məlumat strukturları icad ediblər. Məsələn, siyahılar siyahısı.
Bir çox konteynerlər yeni elementlər əlavə edilərkən və ya mövcud elementlər çıxarıldıqda öz elementlərinin sırasını dəyişir. Məsələn, elementləri sırayla saxlayan bir siyahı var və yeni element əlavə olunduqda, bu element demək olar ki, həmişə siyahının ortasına daxil edilir.
Və belə bir vəziyyət yaranır ki, elementlərə sahib konteyner var, elementlərin özü də var, amma sabit bir sıralama yoxdur.
Amma fərz edək ki, belə bir kolleksiyadakı bütün elementləri bir massivə və ya siyahıya köçürmək istəyirik. Bütün elementləri əldə etməliyik. Bizim üçün onları hansı sırayla keçəcəyimiz önəmli deyil, əsas odur ki, təkrarlanmasın. Bunu necə edə bilərik?
2. Kolleksiyada iterator
Yuxarıda qeyd olunan problemi həll etmək üçün bir həll təklif edildi — iterator.
Iterator — kolleksiyadakı bütün elementləri keçməyə və təkrar etməməyə kömək edən xüsusi bir obyekt.
Hər hansı bir kolleksiyadan iterator əldə etmək bu kod vasitəsilə mümkündür:
Iterator<Tip> it = ad.iterator();
Burada ad
— kolleksiya dəyişəninin adı, Tip
— kolleksiyanın elementlərinin tipi, iterator()
— kolleksiyanın metodu, it
— iterator obyektinin dəyişən adı.
Iterator obyektinin 3 metodu var:
Metod | Təsvir |
---|---|
|
Kolleksiyanın növbəti elementini qaytarır |
|
Hələ keçilməmiş elementlərin olub-olmadığını yoxlayır |
|
Kolleksiyanın cari elementini silir |
Bu metodlar bir qədər Scanner
sinifinin metodlarına bənzəyir: nextInt()
və hasNextInt()
.
Metod next()
iterator aldığımız kolleksiyanın növbəti elementini qaytarır.
Metod hasNext()
kolleksiyada iteratorun qaytarmadığı elementlərin olub-olmadığını yoxlayır.
HashSet çoxluğundakı bütün elementləri ekrana çıxarmaq üçün belə etmək olar:
Kod | Qeydlər |
---|---|
|
String tipli elementləri saxlayan HashSet tipində obyekt yaradırıq.Müxtəlif dillərdəki salamlamaları set -ə əlavə edirik.set çoxluğundan iterator obyektini alırıq.Hələ elementlər varsa Növbəti elementi əldə edirik Elementi ekrana çıxarırıq |
3. for-each
dövrü
Iteratorun əsas mənfi cəhəti odur ki, onun istifadəsi ilə kod, dövr for
istifadəsi ilə müqayisədə daha mürəkkəb görünür.
Gəlin, müqayisə üçün siyahını ekrana həm for
dövründən, həm də iterator vasitəsilə çıxaraq:
Iterator | for dövrü |
---|---|
|
|
Bəli, ArrayList
siyahısının elementlərini dövr ilə keçmək daha qısa və rahatdır.
Ancaq Java tərtibatçıları bizə bir az şəkər qatmağa qərar verdilər. Xoşbəxtliyimizə görə, bu yenidən sintaksis şəkəri idi.
Onlar Java-ya yeni bir dövr növü əlavə etdilər və onu for-each
adlandırdılar. Onun ümumi istifadəsi belə görünür:
for(Tip ad:kolleksiya)
Burada kolleksiya
— kolleksiya dəyişəni adı, Tip
— kolleksiya elementlərinin tipi, ad
— hər iterasiyada növbəti dəyər alan dəyişənin adıdır.
Bu dövr elementləri gizli iterator vasitəsilə keçir. Əslində onun iş prinsipi budur:
for-each dövrü | Compiler’in gördüyü kod: Iterator ilə dövr |
---|---|
|
|
Compiler kodunuza for-each
dövrünü gördüyü zaman sadəcə sağdakı kodu əlavə edir: iterator alma metodunu və lazım olan metod çağırışlarını əlavə edir.
Proqramçılar for-each
dövrünü çox sevirlər və kolleksiyanın bütün elementlərini keçmək lazım olduqda adətən onu istifadə edirlər.
Hətta ArrayList
siyahısını for-each
ilə keçmək qısadır:
for-each dövrü | for dövrü |
---|---|
|
|
4. for-each
dövründə elementin silinməsi
for-each
dövrünün bir mənfi tərəfi var: o, elementləri düzgün silməyi bacarmır. Əgər belə bir kod yazsanız, xəta alacaqsınız.
Kod | Qeyd |
---|---|
|
Element silinərkən xəta baş verəcək! |
Bu çox gözəl və anlaşılan bir koddur, lakin işləməyəcək.
Iterator ilə kolleksiyanı keçərkən onu dəyişmək olmaz.
Bu məhdudiyyətdən yan keçmək üçün üç üsul mövcuddur.
1 Başqa dövrün istifadəsi
Əgər ArrayList
kolleksiyasını keçirsinizsə, i
sayğacı ilə adi dövrdən istifadə edə bilərsiniz.
Kod |
---|
|
Amma bu variant HashSet
və HashMap
kolleksiyaları üçün uyğun deyil
2 Iteratorun açıq istifadəsi
Iteratoru açıq şəkildə istifadə edə bilərsiniz və onun remove()
metodundan istifadə edə bilərsiniz.
İşləyən variant | İşləməyən variant |
---|---|
|
|
Nəzərə alın ki, remove()
metodunu iterator obyektindən çağırırıq! Iterator elementi silmək haqqında «məlumat alacaq» və bu vəziyyəti düzgün emal edə biləcək.
3 Kolleksiyanın kopyasının istifadəsi
Eyni zamanda kolleksiyanın kopyasını yaratmaq mümkündür və for-each
dövründə kopya kolleksiyanı istifadə edərək, elementləri orijinal kolleksiyadan silmək mümkündür.
Kod | Qeyd |
---|---|
|
Kolleksiyanın kopyasını yaratmaq çox asandır Dövr kopya kolleksiyanın iteratorundan istifadə edir. Elementlər list kolleksiyasından silinir. |
Kolleksiyanın kopyası kifayət qədər tez yaradılır: elementlər kopyalanma zamanı dublikat edilməz, yeni kolleksiyada köhnə kolleksiyada olan eynilə həmin elementlərin bağlantıları saxlanılacaq.
GO TO FULL VERSION