JavaRush /Java блогы /Random-KK /Java әзірлеушісіне арналған сұхбаттардағы сұрақтар мен жа...
Константин
Деңгей

Java әзірлеушісіне арналған сұхбаттардағы сұрақтар мен жауаптарды талдау. 10-бөлім

Топта жарияланған
Сәлеметсіз бе! Бір нәрсенің шебері болу үшін қанша сағат қажет? Мен жиі еститінмін: «Кез келген нәрсенің шебері болу үшін 10 000 сағат жұмсау керек». Қорқынышты сан, солай емес пе? Java әзірлеушісіне арналған сұхбаттардағы сұрақтар мен жауаптарды талдау.  10 - 1 бөлімДегенмен, бұл рас па деп ойлаймын? Ал мен бағдарламалау өнерін меңгеру үшін қанша сағат жұмсағанымды анықтауға тырысамын. Ал сол қымбат 10 000 сағаттан өтіп, шебер атансам, мен бұл айырмашылықты сезінемін бе? Әлде мен байқамай олардың үстінен баяғыда басып кеттім бе? Қалай болғанда да, бағдарламашы болу үшін сізге көп уақытты салудың қажеті жоқ. Ең бастысы, оны дұрыс пайдалану. Сіздің басты мақсатыңыз - сұхбаттан өту. Ал жаңадан келгендерге сұхбат бергенде олар біріншіден теория сұрайды, сондықтан сіз оған мықты болуыңыз керек. Шын мәнінде, сұхбатқа дайындалу кезінде сіздің міндетіңіз - Java әзірлеушісінің негізгі теориясындағы барлық олқылықтарыңызды тауып, оларды біліммен қамту. Бүгін мен сізге бұл мәселеде көмектесемін, өйткені мен ең танымал сұрақтарды талдауды жалғастыру үшін келдім. Ендеше жалғастырайық!

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 реттелмеген жиын болып табылады және элементтердің ретін сақтамайды;

  • ArrayList бос мәндердің кез келген санын (нөл) рұқсат етеді, HashSet ішіне тек бір нөлдік мәнді енгізуге болады (ақыр соңында, элементтердің бірегейлігі).

91. Неліктен Java-да динамикалық массив іске асырудың әртүрлілігі бар?

Java әзірлеушісіне арналған сұхбаттардағы сұрақтар мен жауаптарды талдау.  10 - 3 бөлімБұл философиялық сұрақ. Неліктен олар әртүрлі жаңа технологияларды ойлап табады? Ыңғайлылық үшін. Шындығында, бұл динамикалық массив енгізулерінің көп санымен бірдей. Олардың ешқайсысын ең жақсы немесе идеал деп атауға болмайды. Әрқайсысының белгілі бір жағдайда артықшылығы бар. Ал біздің міндетіміз – олардың айырмашылықтарын, күшті/әлсіз жақтарын білу: ең қолайлысын дұрыс жағдайда пайдалана білу үшін.

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 әдіс туралы ақпаратты талқылаудың екінші бөлігіндеJava әзірлеушісіне арналған сұхбаттардағы сұрақтар мен жауаптарды талдау.  10 - 4 бөлім табуға болады .

95. Java тілінде Equals және HashCode не үшін қолданылады?

hashCode() - барлық сыныптарға мұраланған Object класының әдісі . Оның міндеті - белгілі бір нысанды көрсететін кейбір сандарды жасау. Бұл әдісті қолданудың мысалы ретінде жұп сақталатын ішкі массивтің (шелек) ұяшығын анықтайтын жергілікті хэш-codeты одан әрі анықтау үшін негізгі нысандағы HashMap бағдарламасында пайдалану болып табылады. Біз HashMap жұмысы туралы талдаудың 9-бөлімінде егжей-тегжейлі айттық , сондықтан біз бұл туралы көп тоқталмаймыз. Java әзірлеушісіне арналған сұхбаттардағы сұрақтар мен жауаптарды талдау.  10 - 5 бөлімСондай-ақ, әдетте, бұл әдіс an objectілердің сәйкестігін анықтауға арналған оның негізгі құралдарының бірі ретінде equals() әдісінде қолданылады. equals() — an object класының әдісі , оның міндеті нысандарды салыстыру және олардың тең немесе тең еместігін анықтау. Бұл әдіс an objectілерді салыстыру қажет барлық жерде қолданылады, өйткені == көмегімен әдеттегі салыстыру нысандарға жарамайды, өйткені оларға сілтемелерді ғана салыстырады.

96. Java тіліндегі Equals және HashCode арасындағы келісім-шарт туралы айтып беріңізші?

Бірінші айтарым, equals() және hashCode() әдістері дұрыс жұмыс істеуі үшін оларды дұрыс қайта анықтау керек. Осыдан кейін олар келесі ережелерді сақтауы керек:
  • теңдеу арқылы салыстыру ақиқат мәнін қайтаратын бірдей нысандарда бірдей хэш codeтары болуы керек ;
  • бірдей хэш-codeтары бар нысандар әрқашан бірдей болмауы мүмкін.
Осы кезде талдаудың келесі бөліміне дейін үзіліс жасаймыз!Java әзірлеушісіне арналған сұхбаттардағы сұрақтар мен жауаптарды талдау.  10 - 6 бөлім
Сериядағы басқа материалдар:
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION