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 ирээтсиз топтом жана элементтердин тартибин сактаbyte;
-
ArrayList каалаган сандагы бош маанилерге жол берет (нөл), HashSetге бир гана нөл маанини киргизүүгө болот (анткени элементтердин уникалдуулугу).
91. Эмне үчүн Javaда динамикалык массивди ишке ашыруунун мынчалык көп түрдүүлүгү бар?
Ооба, бул философиялык суроо. Ооба, эмне үчүн алар мынчалык көп түрдүү жаңы технологияларды ойлоп табышат? Ыңгайлуу үчүн. Чынында, динамикалык массивди ишке ашыруунун көп саны менен бирдей. Алардын бирин да мыкты же идеал деп атоого болбойт. Ар бир конкреттүү кырдаалда артыкчылыктары бар. Ал эми биздин милдет - алардын айырмачылыктарын, күчтүү/алсыз жактарын билүү: туура кырдаалда эң ылайыктуусун колдоно билүү үчүн.92. Эмне үчүн Java-да ачкыч-маанorк сактоону ишке ашыруунун мынчалык ар түрдүү?
Бул жерде абал динамикалык массивди ишке ашыруудагыдай эле. Мыкты эч ким жок: ар биринин күчтүү жана алсыз жактары бар. Жана биз, албетте, өзүбүздүн күчтүү жактарыбызды максималдуу түрдө пайдаланууга тийишпиз. Мисал: көптөгөн көп агымдуу технологияларды камтыган конкуррент пакетинин өзүнүн Concurrent жыйнактары бар. Ошол эле ConcurrentHashMap кадимки HashMap менен салыштырганда маалыматтар менен көп жиптүү иштин коопсуздугу боюнча артыкчылыкка ээ , бирок көп жиптүү эмес чөйрөдө ал ылдамдыгын жоготот. Эч кандай кырдаалда эң күчтүү болбогон ишке ашыруулар акырындык менен колдонулбай калат. Мисал: Hashtable алгач жип менен коопсуз HashMap болууга арналган , бирок ConcurrentHashMap аны көп жиптүү чөйрөдө жакшы аткарды жана Hashtable акыры унутулуп, колдонулбай калды.93. Элементтер жыйындысы кантип сорттолот?
Биринчи айта турган нерсе, коллекция элементтеринин классы Comparable интерфейсин жана анын compareTo ыкмасын ишке ашыруусу керек . Же сизге Comparator ыкмасы менен компараторду ишке ашырган класс керек . Алар тууралуу кененирээк бул посттон окуй аласыз . Эки ыкма тең берилген типтеги an objectтерди кантип салыштыруу керек экенин аныктайт. Сорттоодо бул өтө маанилүү, анткени сиз элементтерди салыштырууга боло турган принципти түшүнүшүңүз керек. Мунун негизги жолу - Салыштыргычты ишке ашыруу , сиз сорттогуңуз келген класста түздөн-түз ишке ашырылат. Ошол эле учурда Comparator колдонуу азыраак кездешет. Салыштырмалуу ишке ашыруусу жок кээ бир китепкананын классын колдонуп жатасыз дейли , бирок сиз аны кандайдыр бир жол менен иреттешиңиз керек болот. Бул класстын codeун өзгөртө албай туруп (аны кеңейтүүдөн тышкары) Comparator ишке ашырууну жазсаңыз болот , анда бул класстын an objectтерин кандай принципте салыштыргыңыз келгенин көрсөтөсүз. Жана дагы бир мисал. Келгиле, бир типтеги an objectтерди сорттоо үчүн ар кандай принциптер керек дейли, ошондуктан сиз ар кандай кырдаалдарда колдонгон бир нече Салыштыргычтарды жазасыз. Эреже катары, кутудан чыккан көптөгөн класстар салыштырылуучу интерфейсти ишке ашырышат - ошол эле String . Чынында, аларды колдонууда, аларды кантип салыштыруу керек деп тынчсыздануунун кереги жок. Сиз жөн гана аларды алып, аларды колдоно аласыз. Биринчи жана эң айкын жол - элементтер классынын компараторуна ылайык элементтерди мурунтан эле иреттелген тартипте сактаган TreeSet же TreeMap түрүндөгү коллекцияны колдонуу . TreeMap ачкычтарды сорттоп , бирок баалуулуктарды эмес. Эгерде сиз Comparable ордуна Comparator ишке ашырууну колдонсоңуз , анын an objectисин түзүлгөндөн кийин коллекциянын конструкторуна өткөрүп беришиңиз керек болот:TreeSet treeSet = new TreeSet(customComparator);
Бирок сизде коллекциянын башка түрү болсо эмне болот? Аны кантип сорттоо керек? Бул учурда, Collections утorтасынын экинчи ыкмасы ылайыктуу - sort() ыкмасы . Бул статикалык, андыктан класстын аталышы жана керектүү тизме өткөрүлө турган ыкма керек. Мисалы:
Collections.sort(someList);
Эгер сиз Comparable колдонбосоңуз , тескерисинче, Comparator ишке ашырылса , аны экинчи параметр катары өткөрүп беришиңиз керек:
Collections.sort(someList, customComparator);
Натыйжада, өткөн тизменин элементтеринин ички тартиби өзгөрөт: ал элементтердин компараторуна ылайык иргелет. Мен элементтердин өткөрүлүп берилген тизмеси өзгөрмө болушу керек экенин белгилеймин, б.а. өзгөрүлүүчү, антпесе ыкма иштебейт жана UnsupportedOperationException ыргытылат . Үчүнчү жол катары , Салыштырмалуу ишке ашыруу колдонулса, коллекциянын элементтерин сорттоочу Stream сорттоо операциясын колдоно аласыз :
someList = someList.stream().sorted().collect(Collectors.toList());
салыштыруучу болсо :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
Сиз бул макалада Stream жөнүндө көбүрөөк окуй аласыз . Төртүнчү ыкма – бул көбүкчө сорттоо же бириктирүү сыяктуу сорттоону кол менен ишке ашыруу .
ClassObject. Equals жана HashCode
94. Java тorндеги класс an objectисине кыскача мүнөздөмө бериңиз
Анализдин экинчи бөлүгүндө биз Object классынын методдору жөнүндө сүйлөшкөнбүз, жана мен сизге Object классы Javaдагы бардык класстардын улакчысы экенин эскертем . Анын 11 методу бар, аларга жараша бардык класстар тукум кууп өткөн. Бардык 11 ыкмалар тууралуу маалыматты талкуунун экинчи бөлүгүнөн тапса болот .95. Equals жана HashCode Java тorнде эмне үчүн колдонулат?
hashCode() бардык класстар тарабынан мураска алынган Object классынын ыкмасы . Анын милдети - белгилүү бир an objectти чагылдырган кандайдыр бир санды түзүү. Бул ыкманы колдонууга мисал катары аны HashMapда негизги an objectте колдонуу, андан ары жергorктүү хэшcodeду аныктоо болуп саналат, ал жуп сактала турган ички массивдин (чака) уячасын аныктайт. Биз HashMapтын иши жөнүндө талдоонун 9-бөлүгүндө кеңири сүйлөштүк , андыктан бул жөнүндө көп деле токтолбойбуз. Ошондой эле, эреже катары, бул ыкма an objectтердин иденттүүлүгүн аныктоо үчүн анын негизги инструменттеринин бири катары equals() методунда колдонулат. equals() бул Object классынын ыкмасы , анын милдети an objectтерди салыштыруу жана алардын бирдей же тең эместигин аныктоо. Бул ыкма an objectтерди салыштыруу керек болгон бардык жерде колдонулат, анткени == колдонуу менен кадимки салыштыруу an objectтерге ылайыктуу эмес, анткени аларга шилтемелерди гана салыштырат.96. Javaдагы Equals жана HashCode ортосундагы келишим жөнүндө айтып бериңизчи?
Биринчи айта турган нерсе, equals() жана hashCode() методдору туура иштеши үчүн , аларды туура жокко чыгаруу керек. Андан кийин, алар эрежелерди сактоого тийиш:- барабар аркылуу салыштыруу чындыкты кайтарган окшош an objectилерде окшош хэш codeдору болушу керек ;
- бирдей хэш codeдору бар an objectтер дайыма бирдей боло бербейт.
GO TO FULL VERSION