for-each tsikli

All lectures for UZ purposes
Daraja, Dars
Mavjud

1. Iterator paydo bo'lishi tarixi

Siz allaqachon HashSet to'plami bilan tanishgansiz. Va agar siz chindan ham uni o'rganib chiqsangiz, faqat darsni o'qigan bo'lmasangiz, savol tug'ilishi kerak edi:

HashSet'dagi barcha elementlarni ekranga qanday chiqaramiz? Chunki to'plamda get() va set() metodlari yo'q!

Va HashSet bu muammosida yolg'iz emas. HashSetdan tashqari, elementni raqam bo'yicha olish mumkin bo'lmagan ko'plab boshqa kolleksiyalar mavjud, chunki elementlarning aniq tartibi yo'q.

Dasturchilar o'z vaqtida graflar, daraxtlar kabi ko'plab murakkab ma'lumotlar strukturalarini o'ylab topishdi. Yoki, masalan, ro'yxatlar ro'yxati.

Ko'plab konteynerlar yangi elementlar qo'shilganda yoki mavjud elementlar o'chirilganda o'z elementlarining tartibini o'zgartiradi. Masalan, elementlarni o'sib boruvchi tartibda saqlaydigan ro'yxat mavjud va yangi element qo'shilganda, u deyarli har doim ro'yxatning o'rtasiga kiritiladi.

Shunday qilib, bizda elementlarni o'z ichiga olgan konteyner mavjud, lekin aniq tartib mavjud emas.

Agar biz bunday kollektsiyadan barcha elementlarni massiv yoki ro'yxatga nusxalamoqchi bo'lsak, ularning barchasini olishimiz kerak. Biz ularning qaysi tartibda o'tkazilishidan qat'iy nazar, eng muhimi, takrorlanmagan holda o'rganishimiz kerak. Qanday qilib buni qilamiz?


2. Kolektsiyada iterator

Yuqorida keltirilgan muammoni yechish uchun yechim taklif qilindi — iterator.

Iterator — bu kollektsiyaning barcha elementlarini takrorlanmasdan aylanib o'tishga yordam beradigan maxsus obyekt.

Har qanday kollektsiyadan iteratorni olish uchun quyidagi koddan foydalanish mumkin:

Iterator<Type> it = nom.iterator();

Bu erda nom — bu kolleksiya o'zgaruvchining nomi, Type — bu kolleksiyaning elementlari turi. iterator() — bu kolleksiya metodi. it — bu iterator obyekti o'zgaruvchining nomi.

Iterator obyektida 3 ta metod mavjud:

Method Tasvir
Type next()
Koleksiya navbatdagi elementini qaytaradi
boolean hasNext()
Koleksiyada hali bosilmagan elementlar mavjudligini tekshiradi
void remove()
Koleksiyaning joriy elementini o'chiradi

Bu metodlar Scanner sinfining metodlariga o'xshash: nextInt() va hasNextInt().

next() metodi iteratorni olgan koleksiya navbatdagi elementini qaytaradi.

hasNext() metodi kollektsiyada hali iterator tomonidan qaytarilmagan elementlar mavjudligini tekshiradi.

HashSet to'plamining barcha elementlarini qanday chiqarish mumkin:

Kod Izohlar
HashSet<String> set = new HashSet<String>();

set.add("Salom");
set.add("Hello");
set.add("Hola");
set.add("Bonjour");
set.add("Ciao");
set.add("Namaste");

Iterator<String> it = set.iterator();
while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}
HashSet turidagi obyektni yaratamiz, bu esa String turidagi elementlarni saqlaydi.


Turli tillarda set ga salomlashuvlarni kiritamiz.




set to'plamidan iterator obyektini olamiz.
Hali elementlar mavjud bo'lsa

Keyingi elementni olamiz
Elementni ekranga chiqaramiz


3. for-each tsikli

Iteratorning asosiy kamchiliklari shundaki, uning yordamida kod for tsiklidan foydalangandan ko'ra yanada murakkabroq bo'ladi.

Keling, taqqoslash uchun ro'yxatni for tsikli va iterator yordamida chiqaramiz:

Iterator For tsikll
ArrayList<String> list = new ArrayList<String>();

Iterator<String> it = list.iterator();
while (it.hasNext())
{
 String str = it.next();
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();

for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);
   System.out.println(str);
}

Ha, ArrayList ro'yxatining elementlarini tsiklda aylanishi ancha yaxshi, hamma narsa qisqaroq bo'ladi.

Biroq, Java ishlab chiquvchilari yana bir bor shakarni qo'shishga qaror qilishdi. Va yana bir bor, bu sintaktik shakar edi.

Ular Java-ga yangi turdagi tsikl qo'shishdi va uni for-each deb nomlashdi. Mana, uning umumiy foydalanilishi quyidagi ko'rinishda:

for(Type nom:kolleksiya)

Bu erda kolleksiya — bu kolleksiya o'zgaruvchining nomi, Type — bu kolleksiyaning elementlari turi, va nom — bu o'zgaruvchining nomi, bu esa tsiklning har bir aylanishida kolleksiyadan navbatdagi qiymatni qabul qiladi.

Bu tsikl yashirin iterator orqali barcha elementlarni aylantiradi. Mana, u aslida qanday ishlaydi:

For-each tsikli Kompiutor ko'rishi mumkin bo'lgan: Iterator bilan tsikl
ArrayList<String> list = new ArrayList<String>();

for (String str: list)
{
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();
Iterator<String> it = list.iterator();

while (it.hasNext())
{
   String str = it.next();
   System.out.println(str);
}

Kompiulyator sizning kodingizda for-each tsiklini ko'rsa, uni shunchaki o'ngdagi kodga almashtiradi: iterator olish metodini qo'shadi va barcha etishmayotgan metod chaqiruvlarini kiritadi.

Dasturchilar for-each tsiklini juda yaxshi ko'rishadi va kolleksiyaning barcha elementlarini aylantirish kerak bo'lganda deyarli har doim uni ishlatishadi.

Hatto ArrayList ro'yxatini for-each tsikli yordamida aylanishi ham qisqaroq ko'rinadi:

For-each tsikli For tsikli
ArrayList<String> list = new ArrayList<String>();

for (String str: list)
{
   System.out.println(str);
}
ArrayList<String> list = new ArrayList<String>();

for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);
   System.out.println(str);
}


4. for-each tsiklida elementni o'chirish

for-each tsiklning bitta kamchiligi bor: u elementlarni to'g'ri o'chirishni bilmaydi. Agar siz bunday kod yozsangiz, xato olasiz.

Kod Izoh
ArrayList<String> list = new ArrayList<String>();

list.add("Salom");
list.add("Hello");
list.add("Hola");
list.add("Bonjour");
list.add("Ciao");
list.add("Namaste");

for (String str: list)
{
   if (str.equals("Hello"))
      list.remove(str);
}












Elementni o'chirishda xato yuzaga keladi!

Bu juda chiroyli va tushunarli kod, lekin ishlamaydi.

Muhim!

Iterator yordamida kollektsiyani aylantirayotganingizda uni o'zgartirish mumkin emas.

Bu cheklovni chetlab o'tishning uchta usuli mavjud.

1 Boshqa tsikldan foydalanish

Agar siz ArrayList kollektsiyasini aylantirayotgan bo'lsangiz, i hisoblagichi bilan oddiy tsikldan foydalanishingiz mumkin.

Kod
for (int i = 0; i < list.size(); i++)
{
   String str = list.get(i);

   if (str.equals("Hello"))
   {
      list.remove(str);
      i--;    // elementlar siljiganligi uchun i ni kamaytirishimiz kerak
   }
}

Lekin bu variant HashSet va HashMap kolleksiyalari uchun mos emas

2 Iteratordan oshkora foydalanish

Iteratorni oshkora ishlatish va uning remove() metodidan foydalanish mumkin.

Ishlaydigan variant Ishlamaydigan variant
Iterator<String> it = set.iterator();
while (it.hasNext())
{
   String str = it.next();
   if (str.equals("Hello"))
       it.remove();
}

for (String str: list) { if (str.equals("Hello")) list.remove(str); }

E'tibor bering, remove() metodini iterator obyektida chaqiramiz! Iterator elementning o'chirilishi haqida "biladi" va bu vaziyatni to'g'ri qayta ishlay oladi.

3 Kolleksiyaning nusxasidan foydalanish

Shuningdek, siz koleksiyaning nusxasini yaratishingiz va for-each tsiklda nusxa kolleksiyasidan foydalanishingiz, asl kolleksiyadan elementlarni o'chirishingiz mumkin.

Kod Izoh
ArrayList<String> listCopy = new ArrayList(list);

for (String str: listCopy)
{
   if (str.equals("Hello"))
      list.remove(str);
}
Kolleksiya nusxasini yaratish juda oson



Tsikl nusxa kolleksiyasi iteratoridan foydalanadi.
Elementlar list kolleksiyadan o'chiriladi.

Kolleksiya nusxasi tezda yaratiladi: kolleksiya nusxalanayotganda elementlar ikki marta ko'paytirilmaydi, yangi koleksiyada eski kolleksiyadagi elementlarga havolalar saqlanadi.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION