89. ArrayList-тің LinkedList-тен айырмашылығы неде?
Бұл HashMap ішкі құрылымы туралы сұрақпен қатар ең танымал сұрақтардың бірі . Бірде-бір сұхбат онсыз аяқталмайды, сондықтан оған жауап «тістеріңізден шығуы керек». Айқыннан басқа - әртүрлі атаулар - олар ішкі құрылымында ерекшеленеді. Бұрын біз ArrayList және LinkedList екеуінің де ішкі құрылымын қарастырдық , сондықтан мен оларды іске асырудың егжей-тегжейіне тоқталмаймын. Еске сала кетейін, ArrayList ішкі массив негізінде жүзеге асырылады, ол формулаға сәйкес қажетінше көбейтіледі:<размерТекущегоМассива> * 3 / 2 + 1
Сонымен қатар, LinkedList ішкі қосарланған тізім негізінде жүзеге асырылады, яғни әрбір элементте тізімнің басы/соңы болып табылатын мәндерді қоспағанда, алдыңғы және келесіге сілтеме бар. Адамдар бұл сұрақты «Қайсысы жақсы - ArrayList немесе LinkedList ?» форматында қойғанды ұнатады , сізді ұстап алу үшін. Өйткені, олардың біреуін жауап ретінде көрсетсеңіз, ол қате жауап болады. Оның орнына, сіз қандай нақты жағдай туралы айтып жатқаныңызды нақтылауыңыз керек - индекстік қатынас немесе тізімнің ортасына кірістіру. Жауапқа қарай таңдауыңызды түсіндіре аласыз. Мен бұрын ArrayList және LinkedList бір немесе басқа жағдайда қалай жұмыс істейтінін сипаттадым . Салыстыру үшін оларды бір бетке қою арқылы мұны қорытындылайық: Элемент қосу (қосу)
-
Добавление нового element без указания индекса How местоположения будет происходить автоматически в конец обоих списков. В LinkedList новый элемент станет новым хвостом (происходит только перезаписывание пары ссылок — алгоритмическая сложность O(1)).
В ArrayList будет добавлен новый элемент в последнюю пустую ячейку массива — O(1).
-
Добавление element по индексу How правило подразумевает вставку примерно в середину списка. В LinkedList сперва будет вестись поиск нужного места с помощью перебора элементов с “хвоста” и “головы” — O(n/2), а после — вставка значения путем переопределения ссылок элементов, между которыми вставляется новый — O(1). Суммарная алгоритмическая сложность данного действия будет O(n/2).
ArrayList в данной ситуации по индексу находит элемент — O(1), и все элементы справа (включая элемент, который уже хранится по данному индексу) двигаются на одну единицу вправо (при этом возможно понадобится создание нового списка и копирование элементов в него) — O(n/2). Суммарная сложность — O(n/2). -
Добавление element в начало списка в LinkedList будет ситуация схожая с добавлением в конец: новый элемент станет новой “головой” — O(1), в то же время когда ArrayList-у нужно будет двигать все элементы вправо — O(n).
90. ArrayList-тің HashSet-тен айырмашылығы неде?
Егер ArrayList және LinkedList операцияларын салыстыруға болатын болса - бұл жақсырақ - ArrayList-ті HashSet -пен салыстыру оңай емес , өйткені бұл мүлдем басқа жинақтар. Сіз бір тәтті тағамды екіншісімен салыстыра аласыз, бірақ ол ет тағамымен жұмыс істейді - олар тым әртүрлі. Дегенмен, мен олардың арасындағы кейбір айырмашылықтарды беруге тырысамын:-
ArrayList List интерфейсін жүзеге асырады , ал HashSet Set интерфейсін жүзеге асырады ;
-
ArrayList -те қол жеткізу элемент индексі бойынша мүмкін: алу операциясының алгоритмдік күрделілігі O(1) , ал HashSet- те талап етілетін элементті тек дөрекі күшпен алуға болады және бұл O(1) -ден O(n) -ге дейін . ;
-
ArrayList қайталанатын элементтерге мүмкіндік береді. HashSet -те барлық элементтер бірегей болып табылады: аналогы жинақта бұрыннан бар HashSet- ке элемент қосу жұмыс істемейді (көшірмелер хэшcodeы арқылы тексеріледі, демек бұл жинақтың атауы);
-
ArrayList ішкі массив арқылы жүзеге асырылады, ал HashSet ішкі HashMap арқылы жүзеге асырылады ;
-
ArrayList элементтердің кірістіру ретін сақтайды, ал HashSet реттелмеген жиын болып табылады және элементтердің ретін сақтамайды;
-
ArrayList бос мәндердің кез келген санын (нөл) рұқсат етеді, HashSet ішіне тек бір нөлдік мәнді енгізуге болады (ақыр соңында, элементтердің бірегейлігі).
91. Неліктен Java-да динамикалық массив іске асырудың әртүрлілігі бар?
Бұл философиялық сұрақ. Неліктен олар әртүрлі жаңа технологияларды ойлап табады? Ыңғайлылық үшін. Шындығында, бұл динамикалық массив енгізулерінің көп санымен бірдей. Олардың ешқайсысын ең жақсы немесе идеал деп атауға болмайды. Әрқайсысының белгілі бір жағдайда артықшылығы бар. Ал біздің міндетіміз – олардың айырмашылықтарын, күшті/әлсіз жақтарын білу: ең қолайлысын дұрыс жағдайда пайдалана білу үшін.92. Неліктен Java тілінде кілттер-мәнді сақтауды іске асырудың әртүрлілігі бар?
Мұнда жағдай динамикалық массив енгізулеріндегідей. Ең жақсы ешкім жоқ: әрқайсысының күшті және әлсіз жақтары бар. Және біз, әрине, өз күштерімізді барынша пайдалануымыз керек. Мысал: көптеген көп ағынды технологияларды қамтитын бір мезгілде пакетте өзінің Concurrent жинақтары бар. Дәл сол ConcurrentHashMap кәдімгі HashMapмен салыстырғанда деректермен көп ағынды жұмыс қауіпсіздігінде артықшылығы бар , бірақ көп ағынды емес ортада ол жылдамдықты жоғалтады. Кез келген жағдайда ең күшті болып табылмайтын іске асырулар бірте-бірте пайдалануды тоқтатады. Мысал: Hashtable бастапқыда ағынды қауіпсіз HashMap болуға арналған , бірақ ConcurrentHashMap оны көп ағынды ортада басып озды және Hashtable ақырында ұмытылды және енді пайдаланылмады.93. Элементтер жиыны қалай сұрыпталады?
Бірінші айта кететін нәрсе, жинақ элементінің класы Comparable интерфейсін және оның compareTo әдісін жүзеге асыруы керек . Немесе Комапраторды компаратор әдісімен жүзеге асыратын сынып қажет . Олар туралы толығырақ осы посттан оқи аласыз . Екі әдіс те берілген түрдегі нысандарды қалай салыстыру керектігін анықтайды. Сұрыптау кезінде бұл өте маңызды, өйткені элементтерді салыстыруға болатын принципті түсіну керек. Мұны істеудің негізгі жолы - сұрыптағыңыз келетін сыныпта тікелей жүзеге асырылатын Comparable іске асыру. Сонымен қатар Comparator қолдану азырақ кездеседі. Салыстырмалы іске асырылуы жоқ кейбір кітапханадағы сыныпты пайдаланып жатырсыз делік , бірақ оны қандай да бір жолмен сұрыптауыңыз керек. Осы сыныптың codeын өзгерту мүмкіндігінсіз (оны кеңейтуден басқа), сіз осы класс an objectілерін қандай принцип бойынша салыстырғыңыз келетінін көрсететін Comparator іске асыруын жаза аласыз. Және тағы бір мысал. Бір типті an objectілерді сұрыптау үшін әртүрлі принциптер қажет делік, сондықтан сіз әртүрлі жағдайларда қолданылатын бірнеше Салыстырғыштарды жазасыз. Әдетте, қораптан тыс көптеген сыныптар Салыстырмалы интерфейсті - бірдей Жолды іске асырады . Шындығында, оларды пайдаланған кезде оларды қалай салыстыру керектігі туралы алаңдамаудың қажеті жоқ. Сіз оларды жай ғана алып, пайдаланасыз. Бірінші және ең айқын әдіс - элементтер класының компараторына сәйкес элементтерді әлдеқашан сұрыпталған тәртіпте сақтайтын TreeSet немесе TreeMap түріндегі жинақты пайдалану . TreeMap кілттерді сұрыптайтынын есте сақтаңыз , бірақ мәндерді емес. Comparable орнына Comparator іске асырылуын пайдалансаңыз , жасалған кезде оның нысанын коллекция конструкторына беру керек болады:TreeSet treeSet = new TreeSet(customComparator);
Бірақ сізде коллекцияның басқа түрі болса ше? Оны қалай сұрыптауға болады? Бұл жағдайда Collections утorтасының екінші әдісі қолайлы - sort() әдісі . Бұл статикалық, сондықтан сізге тек сыныптың атауы және қажетті тізім жіберілетін әдіс қажет. Мысалы:
Collections.sort(someList);
Егер сіз Comparable қолданбасаңыз , керісінше Comparator қолданбасын іске асырсаңыз , оны екінші параметр ретінде беруіңіз керек:
Collections.sort(someList, customComparator);
Нәтижесінде өткізілген тізім элементтерінің ішкі реті өзгереді: ол элементтердің компараторына сәйкес сұрыпталады. Элементтердің тасымалданатын тізімі өзгермелі болуы керек екенін ескертемін, яғни. өзгермелі, әйтпесе әдіс жұмыс істемейді және UnsupportedOperationException шығарылады . Үшінші әдіс ретінде , Салыстырмалы іске асыру пайдаланылса, жинақтың элементтерін сұрыптайтын Ағынды сұрыптау әрекетін пайдалануға болады :
someList = someList.stream().sorted().collect(Collectors.toList());
Егер салыстырушы :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
Stream туралы толығырақ осы мақаладан оқи аласыз . Төртінші әдіс - көпіршікті сұрыптау немесе біріктіру сұрыптау сияқты сұрыптауды қолмен орындау .
ClassObject. Теңдіктер және HashCode
94. Java тіліндегі класс an objectісіне қысқаша сипаттама беріңіз
Талдаудың екінші бөлігінде біз Object класының әдістері туралы айттық , мен сізге Object класы Java-дағы барлық класстардың бастаушысы екенін еске саламын. Оның 11 әдісі бар, олар сәйкесінше барлық класстарға мұра болады. Барлық 11 әдіс туралы ақпаратты талқылаудың екінші бөлігінде табуға болады .95. Java тілінде Equals және HashCode не үшін қолданылады?
hashCode() - барлық сыныптарға мұраланған Object класының әдісі . Оның міндеті - белгілі бір нысанды көрсететін кейбір сандарды жасау. Бұл әдісті қолданудың мысалы ретінде жұп сақталатын ішкі массивтің (шелек) ұяшығын анықтайтын жергілікті хэш-codeты одан әрі анықтау үшін негізгі нысандағы HashMap бағдарламасында пайдалану болып табылады. Біз HashMap жұмысы туралы талдаудың 9-бөлімінде егжей-тегжейлі айттық , сондықтан біз бұл туралы көп тоқталмаймыз. Сондай-ақ, әдетте, бұл әдіс an objectілердің сәйкестігін анықтауға арналған оның негізгі құралдарының бірі ретінде equals() әдісінде қолданылады. equals() — an object класының әдісі , оның міндеті нысандарды салыстыру және олардың тең немесе тең еместігін анықтау. Бұл әдіс an objectілерді салыстыру қажет барлық жерде қолданылады, өйткені == көмегімен әдеттегі салыстыру нысандарға жарамайды, өйткені оларға сілтемелерді ғана салыстырады.96. Java тіліндегі Equals және HashCode арасындағы келісім-шарт туралы айтып беріңізші?
Бірінші айтарым, equals() және hashCode() әдістері дұрыс жұмыс істеуі үшін оларды дұрыс қайта анықтау керек. Осыдан кейін олар келесі ережелерді сақтауы керек:- теңдеу арқылы салыстыру ақиқат мәнін қайтаратын бірдей нысандарда бірдей хэш codeтары болуы керек ;
- бірдей хэш-codeтары бар нысандар әрқашан бірдей болмауы мүмкін.
GO TO FULL VERSION