JavaRush /Java блогу /Random-KY /Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун...
Константин
Деңгээл

Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи. 10-бөлүк

Группада жарыяланган
Салам! Бир нерсеге уста болуу үчүн канча саат талап кылынат? Мен мындай сөздөрдү көп уктум: "Баардык нерсенин чебери болуу үчүн 10 000 саат коротуш керек." Коркунучтуу сан, туурабы? Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  10-1-бөлүкБирок, мен кызык, бул чынбы? Жана мен тынымсыз программалоо өнөрүн өздөштүрүү үчүн канча саат жумшаганымды аныктоого аракет кылам. Ошол кымбат баалуу 10 000 сааттан өтүп, устат болгондон кийин, мен бул айырманы сеземби? Же мен аларды эчак эле байкабай басып кеттимби? Кандайдыр бир жол менен, программист болуу үчүн, мынчалык көп убакытты жумшоонун кереги жок. Эң башкысы аны туура пайдалануу. Сиздин негизги максат - интервьюдан өтүү. Ал эми жаңы келгендер үчүн интервью бергенде, алар эң биринчи теорияны сурашат, андыктан ал боюнча күчтүү болушуң керек. Чынында, интервьюга даярданууда сиздин милдетиңиз Java иштеп чыгуучунун негизги теориясындагы бардык кемчorктериңизди таап, аларды бorм менен жабуу. Бүгүн мен сизге бул маселеде жардам берем, анткени мен бул жерде эң популярдуу суроолорду талдоону улантуу үчүн келдим. Андыктан уланталы!

89. ArrayList LinkedListтен эмнеси менен айырмаланат?

Бул HashMap ички түзүмү жөнүндө суроо менен бирге абдан популярдуу суроолордун бири болуп саналат . Бир дагы интервью ансыз бүтпөйт, андыктан ага жооп "тишиңизден чыгып кетиши" керек. ачык-айкын тышкары - ар кандай аталыштар - алар ички түзүлүшү боюнча айырмаланат. Мурда биз ArrayList менен LinkedListтин ички түзүмүн карап чыктык , ошондуктан мен аларды ишке ашыруунун деталдарына кирбейм. Эске сала кетейин, ArrayList ички массивдин негизинде ишке ашырылат, ал формула боюнча зарылчылыкка жараша көбөйөт:
<размерТекущегоМассива> * 3 / 2  + 1
Ошол эле учурда, LinkedList ички кош шилтемеленген тизменин негизинде ишке ашырылат, башкача айтканда, ар бир элементте тизменин башталышы/аягы болгон маанилерди кошпогондо, мурунку жана кийинкиге шилтемеси бар. Адамдар бул суроону "Кайсысы жакшы - ArrayList же LinkedList ?" форматында бергенди жакшы көрүшөт . Анткени, алардын бирин жооп катары көрсөтсөң, ал туура эмес жооп болуп калат. Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  10-2-бөлүкАнын ордуна, сиз кайсы конкреттүү кырдаал жөнүндө айтып жатканыңызды такташыңыз керек - индекске жетүү же тизменин ортосуна киргизүү. Жоопко жараша тандооңузду түшүндүрүп бере аласыз. Мен мурда ArrayList менен LinkedListтин тигил же бул кырдаалда кантип иштээрин сүрөттөгөн элем . Келгиле, салыштыруу үчүн аларды бир бетке коюу менен жалпылайлы: Элемент кошуу (кошуу)
  1. Добавление нового element без указания индекса How местоположения будет происходить автоматически в конец обоих списков. В LinkedList новый элемент станет новым хвостом (происходит только перезаписывание пары ссылок — алгоритмическая сложность O(1)).

    В ArrayList будет добавлен новый элемент в последнюю пустую ячейку массива — O(1).

  2. Добавление element по индексу How правило подразумевает вставку примерно в середину списка. В LinkedList сперва будет вестись поиск нужного места с помощью перебора элементов с “хвоста” и “головы” — O(n/2), а после — вставка значения путем переопределения ссылок элементов, между которыми вставляется новый — O(1). Суммарная алгоритмическая сложность данного действия будет O(n/2).

    ArrayList в данной ситуации по индексу находит элемент — O(1), и все элементы справа (включая элемент, который уже хранится по данному индексу) двигаются на одну единицу вправо (при этом возможно понадобится создание нового списка и копирование элементов в него) — O(n/2). Суммарная сложность — O(n/2).

  3. Добавление element в начало списка в LinkedList будет ситуация схожая с добавлением в конец: новый элемент станет новой “головой” — O(1), в то же время когда ArrayList-у нужно будет двигать все элементы вправо — O(n).

Төмөнкү сап: LinkedListте алгоритмдик татаалдык O(1) ден O(n/2) ге чейин өзгөрөт . Башкача айтканда, киргизүү тизменин аягына же башына канчалык жакын болсо, ошончолук тезирээк болот. Ошол эле учурда, ArrayList үчүн ал O(1) ден O(n) чейин өзгөрөт : киргизүү тизменин аягына канчалык жакын болсо, ошончолук тезирээк болот. Элементти (топтомду) орнотуу Бул операция тизмедеги көрсөтүлгөн позицияга элементти жазат, эгерде бар болсо, мурункунун үстүнөн жазат. LinkedList -те бул операция кошууга окшош болот, анткени Бул жерде эң чоң кыйынчылык - бул элементти табуу. Элементти кайра жазуу жуп шилтемелерди кайра жазуу менен ишке ашат, ошондуктан бул жерде да алгоритмдик татаалдык тизменин аягына же башынан позициянын алыстыгына жараша O(1) ден O(n/2) чейин өзгөрөт. Ошол учурда, бул индекс операциясы үчүн керектүү уяча ArrayListтен табылып , ага жаңы элемент жазылат. Индекс издөө, бул операция сыяктуу, O(1) алгоритмдик татаалдыгына ээ . Элементти индекс боюнча алыңыз (алыңыз) LinkedListте элементти алуу башка операцияларды издөө сыяктуу эле принцип боюнча ишке ашат - аягына же башынан алыстыкка жараша, б.а. O(1) ден O(n/2) га чейин . ArrayListте , жогоруда айткандай, массивдеги элементти индекс боюнча табуу O (1) татаалдыгына ээ . Элементти индекс боюнча алып салуу (алып салуу) LinkedList үчүн анын иштөө принциби бул жерде да иштейт: адегенде элемент табылат, андан кийин шилтемелер кайра жазылат - элементтин кошуналары бул элементке шилтемелерди жоготуп, бири-бирине кайрыла башташат, кийин таштанды жыйноочу тарабынан жок кылынат. Башкача айтканда, алгоритмдик татаалдыгы мурдагыдай эле - O(1) ден O(n/2) ге чейин . ArrayList үчүн бул операция жаңы элементти кошуу операциясына көбүрөөк окшош (кошуу). Биринчиден, керектүү элемент табылат - O(1) , андан кийин ал алынып салынат жана анын оң жагында турган бардык элементтер пайда болгон боштукту жабуу үчүн бир бирдик солго жылдырылат. Жок кылуу операциясы кошуу операциясындай эле алгоритмдик татаалдыкка ээ болот - O(1) ден 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да динамикалык массивди ишке ашыруунун мынчалык көп түрдүүлүгү бар?

Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  10-3-бөлүкОоба, бул философиялык суроо. Ооба, эмне үчүн алар мынчалык көп түрдүү жаңы технологияларды ойлоп табышат? Ыңгайлуу үчүн. Чынында, динамикалык массивди ишке ашыруунун көп саны менен бирдей. Алардын бирин да мыкты же идеал деп атоого болбойт. Ар бир конкреттүү кырдаалда артыкчылыктары бар. Ал эми биздин милдет - алардын айырмачылыктарын, күчтүү/алсыз жактарын билүү: туура кырдаалда эң ылайыктуусун колдоно билүү үчүн.

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 ыкмалар тууралуу маалыматты талкуунун экинчи бөлүгүнөнJava иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  10-4-бөлүк тапса болот .

95. Equals жана HashCode Java тorнде эмне үчүн колдонулат?

hashCode() бардык класстар тарабынан мураска алынган Object классынын ыкмасы . Анын милдети - белгилүү бир an objectти чагылдырган кандайдыр бир санды түзүү. Бул ыкманы колдонууга мисал катары аны HashMapда негизги an objectте колдонуу, андан ары жергorктүү хэшcodeду аныктоо болуп саналат, ал жуп сактала турган ички массивдин (чака) уячасын аныктайт. Биз HashMapтын иши жөнүндө талдоонун 9-бөлүгүндө кеңири сүйлөштүк , андыктан бул жөнүндө көп деле токтолбойбуз. Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  10-5-бөлүкОшондой эле, эреже катары, бул ыкма an objectтердин иденттүүлүгүн аныктоо үчүн анын негизги инструменттеринин бири катары equals() методунда колдонулат. equals() бул Object классынын ыкмасы , анын милдети an objectтерди салыштыруу жана алардын бирдей же тең эместигин аныктоо. Бул ыкма an objectтерди салыштыруу керек болгон бардык жерде колдонулат, анткени == колдонуу менен кадимки салыштыруу an objectтерге ылайыктуу эмес, анткени аларга шилтемелерди гана салыштырат.

96. Javaдагы Equals жана HashCode ортосундагы келишим жөнүндө айтып бериңизчи?

Биринчи айта турган нерсе, equals() жана hashCode() методдору туура иштеши үчүн , аларды туура жокко чыгаруу керек. Андан кийин, алар эрежелерди сактоого тийиш:
  • барабар аркылуу салыштыруу чындыкты кайтарган окшош an objectилерде окшош хэш codeдору болушу керек ;
  • бирдей хэш codeдору бар an objectтер дайыма бирдей боло бербейт.
Бул учурда биз анализдин кийинки бөлүгүнө чейин токтойбуз!Java иштеп чыгуучусу үчүн интервьюдан алынган суроолордун жана жооптордун анализи.  10-6-бөлүк
Сериядагы башка материалдар:
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION