6. Тізім туралы айтып беріңіз
Тізім - бұл тізім деп аталатын an objectілердің реттелген құрылымын көрсететін интерфейс. Бұл құрылымның «қулығы» Тізімдегі элементтерді индекс бойынша, яғни Тізімнің ішкі идентификаторы арқылы енгізуге, өзгертуге немесе жоюға болады . Басқаша айтқанда, индекс: «тізімнің басынан қанша элемент бар» дегенді білдіреді. Бірінші Тізім элементінде 0 индексі, екіншісінде 1 индексі бар және т.б. Сонымен, бесінші элемент тізімнің басынан төрт элемент алыс. Жоғарыда айтылғандай, тізімге элементтерді қосу реті маңызды. Сондықтан деректер құрылымы тізім деп аталады . Біз элементтермен индекс бойынша жұмыс істеуге бағытталған осы құрылымға тән әдістерді тізімдейміз:- get - элементті көрсетілген орынға қайтарады (индекс мәні бойынша),
- жою - элементті көрсетілген позицияда жояды,
- set - көрсетілген позициядағы элементті әдісте көрсетілген элементпен ауыстырады.
- push - өткізілген элементті стектің жоғарғы жағына қосады;
- peek - стектің жоғарғы жағында орналасқан элементті қайтарады;
- pop - сонымен қатар стектің жоғарғы жағында орналасқан элементті қайтарады, бірақ оны жояды;
- empty - стектің бос екенін тексереді - ақиқат немесе жоқ - жалған ;
- іздеу – берілген элементті стектен іздейді. Егер элемент табылса, оның стектің жоғарғы жағына қатысты реттік нөмірі қайтарылады. Егер элемент табылмаса, -1 мәні қайтарылады.
7. Карта туралы айтып беріңіз
Жоғарыда айтылғандай, Карта интерфейстердің және олардың іске асырылуының жеке құрылымы бар жинақ болып табылады. Бұл бөлек, өйткені мұнда мәндер бір уақытта емес, «кілт-мән» жұбында сақталады. Картаның негізгі әдістері :- put(K пернесі, V мәні) – Картаға элемент қосу;
- get(Object key) – кілт бойынша мәнді іздеу;
- containKey(Object key) — Картада осы кілттің бар-жоғын тексереді;
- containValue(Object value) - бұл мәннің бар-жоғын Картаны тексереді;
- Remove(Object key) – мәнді оның кілті арқылы жою.
- HashMap - мәндерді кездейсоқ ретпен сақтауға арналған, бірақ карта элементтерін жылдам іздеуге мүмкіндік береді. null кілт сөзі арқылы кілтті көрсетуге мүмкіндік береді , бірақ бір реттен көп емес, өйткені пернелері бірдей жұптар бірінің үстіне бірі жазылады. Негізгі шарт - пернелердің бірегейлігі: мәндерді қайталауға болады (бірнеше нөлдік мәндер болуы мүмкін).
- LinkedHashMap - мәндерді қосылған ретпен сақтайтын HashMap аналогы . Тиісінше, LinkedList сияқты оның тақырыбы бар - қосарланған тізімнің басы. Баптандыру кезінде ол өзін көрсетеді.
LinkedHashMap- те итератор пайдаланылған кезде элементтерге қалай қол жеткізілетінін көрсететін accessOrder бар . AccessOrder қате болса , қатынас элементтер енгізілген ретпен орындалады. Егер шын болса, элементтер соңғы қол жеткізілген тәртіпте болады (соңғы қол жеткізілген элемент соңында орналастырылады).
- TreeMap — элементтерді негізгі мәндер бойынша сұрыптайтын Карта . TreeSet сияқты , бірақ негізгі мәндерге негізделген жұптар үшін. TreeMap сұрыптау ережелерін орнату үшін пернелер Салыстырмалы интерфейсті орындауы керек . Әйтпесе, кілтке бағытталған компаратор ( TreeMap конструкторында көрсетілген ), TreeSet болуы керек - ішіндегі TreeMap нысанымен жүзеге асырылады, онда шын мәнінде барлық сиқырлар орын алады.
TreeMap қолданбасында қызыл-қара ағаштарды пайдаланып сұрыптау туралы толығырақ TreeMap мүмкіндіктері туралы мақаладан оқи аласыз .
- Hashtable HashMap түріне ұқсас , бірақ нөлдерді кілттер немесе мәндер ретінде сақтауға мүмкіндік бермейді . Ол көп ағынды көзқарас тұрғысынан мұқият синхрондалады, бұл өз кезегінде оның көп ағынды көзқарас тұрғысынан қауіпсіз екенін білдіреді. Бірақ бұл іске асыру ескірген және баяу, сондықтан қазір сіз Hashtable-ті жаңа жобаларда көрмейсіз.
8. ArrayList және LinkedList. Қайсысын қолданған дұрыс?
Бұл сұрақ деректер құрылымдарында ең танымал болуы мүмкін және онымен бірге кейбір тұзақтар бар. Оған жауап бермес бұрын, осы деректер құрылымдары туралы көбірек білейік. ArrayList List интерфейсін жүзеге асырады және қажетінше кеңейтілетін ішкі массивте жұмыс істейді. Ішкі массив толығымен толтырылғанда және жаңа элементті енгізу қажет болғанда, өлшемі (oldSize * 1,5) +1 болатын жаңа массив жасалады. Осыдан кейін ескі массивтегі барлық деректер жаңа + жаңа элементке көшіріледі, ал ескісі қоқыс жинаушы арқылы жойылады . Қосу әдісі элементті массивтің соңғы бос ұяшығына қосады. Яғни, бізде 3 элемент бар болса, ол келесі элементті 4-ші ұяшыққа қосады. Негізгі әдістердің орындалуын қарастырайық:- get(int index) – массивтегі элементті индекс бойынша қабылдау O(1) ішінде ең жылдам болып табылады ;
- add(Object obj) - егер ішкі массивте жаңа элемент үшін жеткілікті орын болса, онда қалыпты кірістіру кезінде O(1) уақыт жұмсалады , өйткені қосу соңғы ұяшыққа бағытталған.
Егер бізге жаңа массив құру және оған мазмұнды көшіру қажет болса, онда біздің уақытымыз O(n) массивіндегі элементтер санына тура пропорционал болады ;
- remove(int index) - элементті, мысалы, ортасынан алып тастағанда, біз O(n/2) уақытын аламыз, өйткені оның оң жағындағы элементтерді бір ұяшық артқа жылжыту керек. Сәйкесінше, егер тізімнің басынан өшірілсе, онда O(n), соңынан - O(1);
- add(int index, Object obj) - жоюға ұқсас жағдай: ортасына қосу кезінде оң жақтағы бір ұяшықтағы элементтерді алға жылжыту керек, сондықтан уақыт O(n/2) болады. Әрине, басынан - O(n), соңынан - O(1);
- set(int index, Object obj) - мұнда жағдай басқаша, өйткені тек қажетті элементті тауып, қалғанын жылжытпай оның үстіне жазу керек, сондықтан O(1).
- get(int index) – тізімнің ортасында орналасқан элементті іздегенде, ол қажетті элемент табылғанша барлық элементтерді ретімен іздей бастайды. Логикалық түрде іздеу O(n/2) алуы керек , бірақ LinkedList-те де құйрық бар, сондықтан іздеу екі жақтан бір уақытта жүзеге асырылады. Сәйкесінше, уақыт O(n/4) дейін қысқарады .
Егер элемент тізімнің басына немесе соңына жақын болса, онда уақыт O(1) болады ;
- add(Object obj) - жаңа элементті қосқанда, «құйрық» элементінде келесі элементке сілтеме қосылады, ал жаңасы осы алдыңғы элементке сілтеме алады және жаңа «құйрық» болады. Сәйкесінше, уақыт O(1) болады ;
- remove(int index) - get(int index) әдісіне ұқсас логика . Элементті тізімнің ортасынан жою үшін алдымен оны табу керек. Бұл қайтадан O(n/4) , ал жоюдың өзі іс жүзінде ештеңе алмайды, өйткені ол тек көрші нысандардың көрсеткішін өзгертеді (олар бір-біріне сілтеме жасай бастайды). Егер элемент басында немесе соңында болса, онда қайтадан - O(1) ;
- add(int index, Object obj) және set(int index, Object obj) - әдістердің алу(int index) уақыт күрделілігі бірдей болады , өйткені уақыттың көп бөлігі элементті іздеуге жұмсалады. Сондықтан тізімнің ортасы үшін - O(n/4) , басы үшін - O(1).
Операция | Массивтер тізімі | LinkedList |
---|---|---|
Индекс бойынша алу (индекс) | O(1) | Ортасында O(n/4) |
Жаңа элемент қосу add(obj) |
O(1) Массивті көшіру қажет болса, онда - O(n) |
O(1) |
Элементті жою (int индексі) |
Басынан - O(n) Ортасынан - O(n/2) Соңынан - O(1) |
Ортасында - O(n/4) Соңында немесе басында - O(n) |
Элементті қосу add(int index, Object obj) |
Жоғарыға оралу - O(n) Ортасына - O(n/2) Соңына дейін - O(1) |
Ортасында - O(n/4) Соңында немесе басында - O(n) |
Элементтер жиынын ауыстыру(индекс, obj) | O(1) |
Ортасында - O(n/4) Соңында немесе басында - O(n) |
- ең жиі орындалатын операция элементті іздеу, элементті қайта жазу болса, ең жақсы таңдау;
- ең нашар таңдау, егер операция басында-ортасында кірістіру және жою болса, өйткені оң жақта элементтердің ауысу операциялары орын алады.
- ең жақсы таңдау, егер біздің жиі операциямыз басынан ортасына кірістіру және жою болса;
- ең көп таралған операция іздеу болса, ең нашар таңдау.
9. HashMap-те элементтер қалай сақталады?
HashMap жинағында ұяшықтары шелек деп аталатын ішкі жиым Node[] кестесі бар . Түйін мыналарды қамтиды:- кілт - кілтке сілтеме,
- мән — мәнге сілтеме,
- хэш - хэш мәні,
- келесі - келесі түйінге сілтеме .
- Кілт нөлге тексеріледі . Егер ол null болса, онда кілт кестенің [0] ұяшығында сақталады, себебі null үшін хэш codeы әрқашан 0 болады.
- Егер кілт null болмаса , онда негізгі нысанның хэшcode() әдісі деп аталады , ол өзінің хэш codeын қайтарады. Бұл хэш codeы Түйін нысаны сақталатын жиым ұяшығын анықтау үшін пайдаланылады.
- Әрі қарай, бұл хэшcode хэшcodeты есептейтін ішкі hash() әдісіне орналастырылады , бірақ кесте [] массивінің өлшемі ішінде .
- Әрі қарай, хэш мәніне байланысты Түйін кестенің [] массивіндегі белгілі бір ұяшыққа орналастырылады .
- Ағымдағы Түйін элементін сақтау үшін пайдаланылатын кесте [] ұяшығы бос болмаса, бірақ әлдеқашан элементі бар болса, Түйін элементтері соңғы элементке жеткенше келесі мәнде қайталанады. Яғни, келесі өрісі null болатын өріс .
Бұл іздеу кезінде қорғалған Түйін нысанының кілті ізделетіндердің кілттерімен салыстырылады:
- егер сәйкестік табылса, іздеу аяқталады және жаңа Түйін сәйкестік табылған Түйінді қайта жазады (тек оның мән өрісі қайта жазылады );
- егер кілт сәйкестіктері табылмаса, жаңа Түйін осы тізімдегі соңғы болады, ал алдыңғысының оған келесі сілтемесі болады.
10. Итератор туралы түсіндіріңіз
Жоғарыдағы Жинақ иерархиясын салыстыру диаграммасында Жинақ интерфейсі бүкіл иерархияның басталған жері болды, бірақ іс жүзінде олай емес. Коллекция Iterator<E> интерфейсін жүзеге асыратын нысанды қайтаратын iterator() әдісі бар интерфейстен мұра алады . Итератор интерфейсі келесідей көрінеді:public interface Iterator <E>{
E next();
boolean hasNext();
void remove();
}
next() - осы әдісті шақыру арқылы келесі элементті алуға болады. hasNext() – келесі элементтің бар-жоғын және жинақтың соңына жеткен-жетпегенін білуге мүмкіндік береді. Әлі де элементтер болған кезде hasNext() true мәнін қайтарады . Әдетте, hasNext() келесі() әдісінің алдында шақырылады , өйткені next() коллекцияның соңына жеткенде NoSuchElementException шығарады . remove() - next() соңғы қоңырау арқылы алынған элементті жояды . Итератордың мақсаты - элементтерді қайталау. Мысалы:
Set<Integer> values = new TreeSet<>();
values.add(5);
values.add(3);
values.add(6);
values.add(8);
values.add(2);
values.add(4);
values.add(1);
values.add(7);
Iterator<Integer> iter = values.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
Шындығында, for-her циклі итератор арқылы сорғыштың астында жүзеге асырылады. Бұл туралы толығырақ мына жерден оқи аласыз . List итератордың өз нұсқасын ұсынады, бірақ салқын және күрделірек - ListIterator . Бұл интерфейс Итераторды кеңейтеді және қосымша әдістерге ие:
- жинақта алдыңғы элемент болса, hasPrevious шын мәнін қайтарады, әйтпесе false;
- алдыңғы ағымдағы элементті қайтарады және алдыңғысына ауысады; егер жоқ болса, онда NoSuchElementException жіберіледі;
- add өткен нысанды next() келесі шақыруымен қайтарылатын элементтің алдында кірістіреді ;
- жиын ағымдағы элементке берілген нысанға сілтеме тағайындайды;
- nextIndex келесі элементтің индексін қайтарады. Егер мұндай нәрсе болмаса, онда тізімнің өлшемі қайтарылады;
- previousIndex алдыңғы элементтің индексін қайтарады. Егер жоқ болса, онда -1 саны қайтарылады.
GO TO FULL VERSION