JavaRush /Java blogi /Random-UZ /Java tilidagi dinamik massivlar

Java tilidagi dinamik massivlar

Guruhda nashr etilgan
Turli darajadagi murakkablikdagi dasturlarni yaratishda har bir ishlab chiquvchi ko'plab ma'lumotlar turlaridan, jumladan massivlardan foydalanadi. Ushbu tuzilma bir turdagi to'plamni saqlash uchun juda mos keladi, ajoyib ishlashni ta'minlaydi va odatda qulaydir. Java tilidagi dinamik massivlar - 1Massivlarning muhim kamchiligi shundaki, ular statikdir: ularning o'lchamlari oldindan belgilanishi kerak. Biroq, dasturchilar kelajakni qanday bashorat qilishni hali bilishmaydi (agar, albatta, AI paydo bo'lmasa, u ma'lumotni juda tez qayta ishlaydi va har qanday voqeani bashorat qila oladi). Shu sababli biz dastur ishlayotgan vaqtda uning hajmini o'zgartira oladigan struktura yaratdik. U dinamik massiv deb ataladi .

JavaRush kursidagi dinamik massivlar

Ushbu mavzu Java Sintaksis kvestida JavaRush kursining 7-darajasida va qisman 8-darajasida juda tushunarli va aniq yoritilgan . Bir nechta ma'ruzalar va 18 ta muammolar davomida asosiy masalalar, dinamik massivlarning turlari va ular orasidagi farq, shu jumladan ishlash ko'rsatkichlari yoritilgan. Ushbu mavzu juda muhim, chunki dinamik massivlar ishlab chiquvchini depressiyadan, bosh og'rig'idan xalos qiladi va aql bovar qilmaydigan vaqtni tejaydi.

Dinamik massiv nima?

Dinamik massiv - bu dasturni bajarish jarayonida o'z hajmini o'zgartira oladigan massiv. Java-da bu rolni asosan ArrayList va LinkedList sinflari bajaradi. Massivlardan farqli o'laroq, ArrayList va LinkedList faqat mos yozuvlar ma'lumotlar turlarini o'z ichiga oladi, ya'ni ular faqat ob'ektlarni saqlashi mumkin. Yaxshiyamki, Java-da ibtidoiy turlarni dinamik massivlarda saqlash imkonini beruvchi autoboxing va autounboxing mexanizmlari mavjud. Statik massiv singari, dinamik massiv ham bir hildir, ya'ni u bitta ma'lumot turini saqlashi mumkin. Biroq, meros mexanizmi va interfeyslardan to'g'ri foydalanish tufayli bitta dinamik massivda bitta umumiy sinfdan meros bo'lib qolgan turli xil sinflarning butun majmuasini saqlash mumkin, lekin quyida ko'proq. Ya'ni, statik massiv shunday ishlaydi: Java-dagi dinamik massivJava tilidagi dinamik massivlar - 2 esa quyidagicha ishlaydi (uchinchi bosqichdagi diagrammani davom ettirgan holda): Java massivni nusxalash uchun maxsus mahalliy funksiyadan foydalanadi, shuning uchun bunday "ko'chirish" unchalik emas. qimmat. Java tilidagi dinamik massivlar - 3

Nima uchun bizga dinamik massiv kerak?

Java tilidagi dinamik massiv dasturni yozish vaqtida hajmi noma'lum bo'lgan bir hil ma'lumotlar to'plamini qayta ishlash uchun ishlatiladi. Misol uchun, siz hozirda ilovadan foydalanayotgan har bir mijozning ma'lumotlarini keshlashni xohlashingiz mumkin. Bunday mijozlar sonini oldindan aytib bo'lmaydi. Dinamik massivlarsiz bu muammoni quyidagi variantlar bilan hal qilish mumkin:
  1. Ehtiyojni 100% qoplaydigan katta massiv yarating;
  2. Bufer vazifasini bajaradigan statik massiv yarating;
  3. To'plamlar kabi boshqa dinamik tuzilmalarni qo'llang.
Birinchi variant faqat qat'iy cheklangan diapazonda mos keladi. Boshqa hollarda, bunday massiv xotirada katta hajmdagi joyni egallaydi, bu juda samarasiz. Ikkinchisi buferni tozalash, o'qish va hokazolar uchun qo'shimcha mexanikani amalga oshirishni talab qiladi. Uchinchisi ham funksionallikdagi farqlar tufayli kamchiliklarga ega.

Java'da dinamik massivning vazifasi nima

Java tilida ArrayList va LinkedList sinflari dinamik massiv vazifasini bajaradi. Eng ko'p ishlatiladigan ArrayList, chunki u ikki marta bog'langan ro'yxat kontseptsiyasini amalga oshiradigan LinkedListdan farqli o'laroq klassik massiv vazifasini bajaradi. Bu haqda biroz keyinroq gaplashamiz.

ArrayList, LinkedList - tushunchalar va ishlash qoidalari

ArrayList klassik massiv bo'lib, dasturni bajarish jarayonida kengaytirilishi mumkin. U oddiy massivga asoslangan: yaratilganda uning hajmi 10 ta elementni tashkil qiladi. Hajmi oshgani sayin, sig'im ortadi. ArrayList ishlaydigan qoidalar:
  • Xuddi statik massiv kabi, u 0 dan indekslanadi;
  • Oxirida kiritish va indeks bo'yicha kirish juda tez - O(1);
  • Elementni boshiga yoki o'rtasiga kiritish uchun siz barcha elementlarni bitta katakchadan o'ngga nusxalashingiz, so'ngra kerakli joyga yangi elementni joylashtirishingiz kerak bo'ladi;
  • Qiymat bo'yicha kirish elementlar soniga bog'liq - O(n);
  • Klassik massivdan farqli o'laroq, u nullni saqlashi mumkin;
LinkedList holatida hamma narsa biroz murakkabroq: u ikki marta bog'langan ro'yxatga asoslangan. Ya'ni, tizimli ravishda ushbu dinamik Java massivi bir-biriga murojaat qiladigan tarqoq ob'ektlar sonidir. Rasmlar bilan tushuntirish osonroq. LinkedList ichida bizda asosiy ob'ekt mavjud bo'lib Head, u elementlar soni haqidagi ma'lumotlarni, shuningdek, birinchi va oxirgi elementlarga havolani saqlaydi: Java tilidagi dinamik massivlar - 4Endi maydon size = 0, firstva last = null. Ushbu ro'yxatga qo'shilgan har bir element alohida ichki ob'ektning mazmunidir. Keling, element qo'shamiz Johnny: Java tilidagi dinamik massivlar - 5Endi bizda "Jonni" qiymatiga ega tugun mavjud. Asosiy element uchun birinchi va oxirgi elementga havolalar yangi tugunga ishora qiladi. Ushbu ob'ektda oldingi va keyingi elementlarga havolalar ham mavjud. Avvalgisiga havola har doim null bo'ladi, chunki bu birinchi element va keyingisiga havola har doim null bo'ladi, chunki u hali mavjud emas. Keling, buni tuzatamiz: Java tilidagi dinamik massivlar - 6"Uotson" qiymatiga ega yangi element qo'shildi, bu ikkinchi bo'ldi. nextE'tibor bering, birinchi elementda keyingi elementga ishora qiluvchi maydon , yangi elementda esa previousavvalgisiga ishora qiluvchi maydon mavjud. Asosiy element uchun oxirgi elementga havola endi yangi tugunga ishora qiladi. Quyidagi diagrammada roʻyxatning oʻrtasiga elementlarni qanday qoʻshish mumkinligi koʻrsatilgan: Java tilidagi dinamik massivlar - 7“Hamish” yangi elementi qoʻshildi. Uni ro'yxatning o'rtasiga kiritish uchun rasmda ko'rsatilganidek, elementlarga havolalarni qayta tayinlash kifoya. Bu illyustratsiyalar yuqori darajadagi ikki marta bog'langan ro'yxat jarayonini batafsil bayon qilmasdan tushuntiradi. LinkedList haqidagi hikoyani umumlashtirish uchun biz uning ishlashi uchun bir nechta qoidalarni olishimiz mumkin:
  • Xuddi massiv kabi, u 0 dan indekslanadi;
  • Birinchi va oxirgi elementga kirish elementlar soniga bog'liq emas - O(1);
  • Indeks bo'yicha elementni olish, ro'yxat o'rtasidan qo'shish yoki o'chirish elementlar soniga bog'liq - O(n);
  • Siz iterator mexanizmidan foydalanishingiz mumkin: keyin kiritish va o'chirish doimiy vaqtda sodir bo'ladi;
  • Klassik massivdan farqli o'laroq, u nullni saqlashi mumkin.

Kod misollari

Keling, ba'zi misollarni ko'rib chiqaylik. Kod parchalari ArrayList va LinkedList uchun misollarni o'z ichiga oladi.

Yaratilish

// Создаем новый список
ArrayList<String> arrayList = new ArrayList<>();
// Создается новый список и указывается начальный размер внутреннего массива
ArrayList<String> arrayListLarge = new ArrayList<>(100000);

// Создаем новый LinkedList
LinkedList<String> linkedList = new LinkedList<>();

Element qo'shish

// Новый элемент добавляется в конец
arrayList.add("Johhny");
// Новый элемент добавляется в указанную позицию (в данном случае — в начало)
arrayList.add(0, "Watson");

// Новый элемент добавляется в конец двусвязного списка
linkedList.add("Java");
// Новый элемент добавляется в нулевую позицию списка:
linkedList.addFirst("I think");
// Новый элемент добавляется в конец списка
linkedList.addLast("language");
// Новый элемент добавляется в указанную позицию
linkedList.add(2, "is a terrific");

// Получение размера списков
int arraySize = arrayList.size(); // 2
int linkedSize = linkedList.size(); // 4
Bir qarashda add()AND usullari addLast()bir xil funksiyani bajaradi, lekin usul add()LinkedList-ga interfeysdan List, usul esa addLastinterfeysdan keldi Deque. LinkedList ikkala interfeysni ham amalga oshiradi. Bu holatda yaxshi amaliyot kontekstga eng mos keladigan usuldan foydalanish bo'ladi. Agar LinkedList navbat sifatida ishlatilsa, eng yaxshisi addLast. Agar LinkedList ro'yxat sifatida ishlatilsa, dan foydalanish o'rinli bo'ladi add().

Elementni olib tashlash

// Удаление element по индексу
arrayList.remove(0);
// Удаление element по значению
arrayList.remove("Johnny");

// Удаление первого element в списке
linkedList.removeFirst();
// Удаление первого element в списке, фактически вызов предыдущего метода
linkedList.remove();
// Удаление последнего element в списке
linkedList.removeLast();
// Удаление первого вхождения element в список
linkedList.removeFirstOccurrence("language");
// Удаление последнего вхождения element в список
linkedList.removeLastOccurrence("Java");
// Удаление по индексу
linkedList.remove(2);
Agar ob'ekt indeks bo'yicha o'chirilgan bo'lsa, usul o'chirilgan ob'ektni qaytaradi. Agar ob'ekt qiymat bo'yicha o'chirilgan bo'lsa (yoki LinkedList ning birinchi yoki oxirgi elementlari o'chirilsa), ob'ekt topilsa va o'chirilsa, usul "true ", aks holda "false" qiymatini qaytaradi .

Elementga kirish va ro'yxatni qidirish

// Доступ к элементу по индексу
String arrayElement = arrayList.get(2);
// Поиск element по значению
int arrayIndex = arrayList.indexOf("Watson");
// Поиск последнего индекса вхождения element в список
int lastArrayIndex = arrayList.lastIndexOf("Watson");

// Доступ по индексу
String linkedElement = linkedList.get(3);
// Получение первого element
String firstLinkedElement = linkedList.getFirst();
// Получение последнего element
String lastLinkedElement = linkedList.getLast();

// Поиск element по значению
int linkedIndex = linkedList.indexOf("Java");
// Поиск последнего индекса вхождения element в список
int lastLinkedIndex = linkedList.lastIndexOf("Java");

Bir halqada yurish

// Использование обычного цикла
for(int i = 0; i<arrayList.size(); i++) {
  String value = arrayList.get(i);
  System.out.println(value);
}

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

// Использование цикла for-each
for(String s : arrayList) {
  System.out.println(s);
}

for(String s : linkedList) {
  System.out.println(s);
}
Bu erda qidiruv haqida bir necha so'z aytishga arziydi. Ko'pgina yangi ishlab chiquvchilar, ro'yxatdagi elementni qidirayotganda, indexOf()va usullari mavjudligiga qaramay, barcha elementlarni qidirilgan bilan solishtirib, tsiklda qidirishni boshlaydilar lastIndexOf(). contains()Ro'yxatda element mavjudligini aniqlash uchun usuldan ham foydalanishingiz mumkin :
boolean isContainsSherlock = arrayList.contains("Sherlock");
boolean isContainsPhp = linkedList.contains("Php");

Qo'shimcha o'qish uchun havolalar

  1. Bu erda ArrayList dan elementlarni olib tashlash haqida ajoyib maqola mavjud . Bu dinamik Java massivi bo'lganligi sababli , elementlarni olib tashlashda juda ko'p nozikliklar mavjud.
  2. ArrayList ning ishlashi bu yerda batafsil tasvirlangan .
  3. LinkedList haqida bir oz ko'proq .
  4. ArrayList va LinkedList haqida Habrdan bir nechta maqolalar .
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION