Ар кандай деңгээлдеги татаалдыктагы программаларды түзүүдө ар бир иштеп чыгуучу көптөгөн маалыматтардын түрлөрүн, анын ичинде массивдерди колдонот. Бул структура бир типтеги топтомду сактоо үчүн абдан ылайыктуу, мыкты аткарууну камсыз кылат жана жалпысынан ыңгайлуу. Массивдердин олуттуу кемчorги алардын статикалык болушунда: алардын өлчөмү алдын ала көрсөтүлүшү керек. Бирок, программисттер келечекти алдын ала кантип болорун бorшпейт (албетте, информацияны укмуштуудай тез иштете турган жана ар кандай окуяларды алдын ала айта ала турган AI пайда болбосо). Ушул себептен улам, биз программа иштеп жатканда анын өлчөмүн өзгөртө ала турган структураны түздүк. Ал динамикалык массив деп аталат .
JavaRush курсундагы динамикалык массивдер
Бул тема Java Syntax квестинде JavaRush курсунун 7-деңгээлинде жана жарым-жартылай 8-деңгээлинде абдан түшүнүктүү жана так чагылдырылган . Бир нече лекциялардын жана 18ге жакын маселелердин жүрүшүндө негизги маселелер, динамикалык массивдердин түрлөрү жана алардын ортосундагы айырмачылык, анын ичинде аткаруучулук камтылган. Бул тема өтө маанилүү, анткени динамикалык массивдер иштеп чыгуучуну депрессиядан, баш оорудан арылтат жана укмуштуудай убакытты үнөмдөйт.
Динамикалык массив деген эмне?
Динамикалык массив – бул программанын аткарылышы учурунда өзүнүн өлчөмүн өзгөртө алган массив. Javaда бул ролду негизинен ArrayList жана LinkedList класстары ойнойт. Массивдерден айырмаланып, ArrayList жана LinkedList шилтеме маалымат түрлөрүн гана камтыйт, башкача айтканда, алар an objectтерди гана сактай алышат. Бактыга жараша, Java динамикалык массивдерде примитивдүү типтерди сактоого мүмкүндүк берген автобокс жана автобокс механизмдери бар. Статикалык массив сыяктуу эле, динамикалык массив да бир тектүү, башкача айтканда, бир типтеги маалыматтарды сактай алат. Бирок, мурастоо механизминин жана интерфейстерди туура колдонуунун аркасында бир динамикалык массивде бир жалпысынан тукум кууган ар кандай класстардын бүтүндөй диапазонун сактоого болот, бирок төмөндө бул боюнча көбүрөөк. Башкача айтканда, статикалык массив мындай иштейт: Жана Javaдагы динамикалык массив төмөнкүдөй иштейт (үчүнчү кадамдагы диаграмманы улантуу): Java массивди көчүрүү үчүн атайын жергorктүү функцияны колдонот, андыктан мындай "жылуу" анчалык деле эмес. кымбат.Эмне үчүн бизге динамикалык массив керек?
Javaдагы динамикалык массив программа жазылган учурда өлчөмү белгисиз болгон бир тектүү маалыматтардын топтомун иштетүү үчүн колдонулат. Мисалы, сиз учурда колдонмону колдонуп жаткан ар бир кардардын маалыматтарын кэштесеңиз болот. Мындай кардарлардын санын алдын ала айтуу мүмкүн эмес. Динамикалык массивдер жок болсо, бул маселени төмөнкү жолдор менен чечсе болот:- 100% муктаждыкты жабууга мүмкүн болгон чоң массивди түзүңүз;
- буфер катары иштей турган статикалык массивди түзүңүз;
- Башка динамикалык структураларды, мисалы, топтомдорду колдонуңуз.
Java'да динамикалык массив эмне кылат?
Java тorнде ArrayList жана LinkedList класстары динамикалык массивдин ролун аткарышат. Эң көп колдонулганы ArrayList, анткени ал классикалык массивдин ролун аткарат, ал LinkedList-тен айырмаланып, кош байланышкан тизменин концепциясын ишке ашырат. Бул тууралуу бир аздан кийин сүйлөшөбүз.ArrayList, LinkedList - түшүнүктөр жана иштөө эрежелери
ArrayList - бул программаны аткаруу учурунда кеңейтorши мүмкүн болгон классикалык массив. Ал кадимки массивге негизделген: түзүлгөндө анын өлчөмү 10 элементти түзөт. Өлчөмү чоңойгон сайын кубаттуулугу да көбөйөт. ArrayList иштеген эрежелер:- Статикалык массив сыяктуу эле, ал 0ден индекстелет;
- Аягына киргизүү жана индекс боюнча жетүү абдан тез - O(1);
- Элементти башына же ортосуна кыстаруу үчүн, бардык элементтерди бир уячаны оңго көчүрүп, андан соң жаңы элементти керектүү жерге чапташыңыз керек болот;
- Маани боюнча жетүү элементтердин санына жараша болот - O(n);
- Классикалык массивден айырмаланып, ал нөлдү сактай алат;
Head
, анда элементтердин саны жөнүндө маалымат сакталат, ошондой эле биринчи жана акыркы элементтерге шилтеме: Азыр талаа size = 0
, first
жана last = null
. Бул тизмеге кошулган ар бир элемент өзүнчө ички an objectтин мазмуну болуп саналат. Келгиле, элементти кошолу Johnny
: Эми бизде "Джонни" мааниси бар түйүн бар. Негизги элемент үчүн биринчи жана акыркы элементке шилтемелер жаңы түйүндү көрсөтөт. Бул an objectтин мурунку жана кийинки элементтерге шилтемелери да бар. Мурункуга шилтеме дайыма нөл болот, анткени бул биринчи элемент, ал эми кийинкиге шилтеме дайыма нөл болот, анткени ал азырынча жок. Муну оңдойлу: "Уотсон" мааниси менен жаңы элемент кошулду, ал экинчи болуп калды. Биринчи элементте next
кийинки элементке, ал эми жаңы элементте previous
мурункуга ишарат кылган талаа бар экенин эске алыңыз. Негизги элемент үчүн акыркы элементке шилтеме эми жаңы түйүндү көрсөтөт. Төмөнкү диаграмма тизменин ортосуна элементтерди кантип кошууну көрсөтөт: "Хамиш" жаңы элементи кошулду. Аны тизменин ортосуна киргизүү үчүн, сүрөттө көрсөтүлгөндөй, элементтерге шилтемелерди кайра дайындаңыз. Бул иллюстрациялар майда-чүйдөсүнө чейин кирбестен, жогорку деңгээлдеги кош байланышкан тизменин процессин түшүндүрөт. LinkedList жөнүндө окуяны жалпылоо үчүн, биз анын иштеши үчүн бир нече эрежелерди чыгара алабыз:
- Массив сыяктуу эле, ал 0ден индекстелет;
- Биринчи жана акыркы элементке жетүү элементтердин санына көз каранды эмес - O(1);
- Индекс боюнча элементти алуу, тизменин ортосунан киргизүү же жок кылуу элементтердин санына жараша болот - O(n);
- Сиз итератор механизмин колдоно аласыз: анда киргизүү жана жок кылуу туруктуу убакытта болот;
- Классикалык массивден айырмаланып, ал нөлдү сактай алат.
Код мисалдары
Келгиле, кээ бир мисалдарды карап көрөлү. Код үзүндүлөрү ArrayList жана LinkedList үчүн мисалдарды камтыйт.Жаратуу
// Создаем новый список
ArrayList<String> arrayList = new ArrayList<>();
// Создается новый список и указывается начальный размер внутреннего массива
ArrayList<String> arrayListLarge = new ArrayList<>(100000);
// Создаем новый LinkedList
LinkedList<String> linkedList = new LinkedList<>();
Элемент кошуу
// Новый элемент добавляется в конец
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
Бир караганда, add()
ЖАНА методдору addLast()
бирдей функцияны аткарат, бирок метод add()
LinkedListке интерфейстен келди List
, ал эми метод addLast
интерфейстен келди Deque
. LinkedList бул интерфейстердин экөөнү тең ишке ашырат. Бул учурда контекстке эң ылайыктуу ыкманы колдонуу жакшы практика болмок. Эгерде LinkedList кезек катары колдонулса, анда addLast
. Эгерде LinkedList тизме катары колдонулса, колдонуу туура болмок add()
.
Элементти алып салуу
// Удаление 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);
Эгерде an object индекс боюнча жок кылынса, метод жок кылынган an objectти кайтарат. Эгерде an object маани боюнча жок кылынса (же LinkedListтин биринчи же акыркы элементтери жок кылынса), метод an object табылып, жок кылынса, чындыкты кайтарат, башка учурда жалган .
Бир нерсеге жетүү жана тизмеден издөө
// Доступ к элементу по индексу
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");
Илмек менен жүрүү
// Использование обычного цикла
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);
}
Бул жерде издөө жөнүндө бир нече сөз айтууга болот. Көптөгөн башталгыч иштеп чыгуучулар тизмедеги элементти издеп жатканда, издөөнү циклде башташат, бардык элементтерди изделген элементтер менен салыштырып, методдор indexOf()
жана lastIndexOf()
. contains()
Тизмеде элемент бар экенин билүү үчүн сиз дагы ыкманы колдонсоңуз болот :
boolean isContainsSherlock = arrayList.contains("Sherlock");
boolean isContainsPhp = linkedList.contains("Php");
Андан ары окуу үчүн шилтемелер
- Бул жерде ArrayListтен элементтерди алып салуу жөнүндө сонун макала бар . Бул динамикалык Java массиви болгондуктан , элементтерди алып салууда көптөгөн кылдаттыктар бар.
- ArrayListтин иштеши бул жерде майда-чүйдөсүнө чейин сүрөттөлгөн .
- LinkedList жөнүндө бир аз көбүрөөк .
- ArrayList жана LinkedList жөнүндө Хабрдан бир нече макала .
GO TO FULL VERSION