Otázky týkajúce sa rozhovoru so zbierkami Java

Tento článok je súčasťou série: • Otázky týkajúce sa rozhovorov o zbierkach Java (aktuálny článok) • Otázky týkajúce sa rozhovorov so systémom Java Type

• Otázky týkajúce sa rozhovorov o súbehu Java (+ odpovede)

• Otázky týkajúce sa štruktúry triedy Java a inicializácie

• Otázky týkajúce sa rozhovoru s Java 8 (+ odpovede)

• Správa pamäte v otázkach týkajúcich sa rozhovorov Java (+ odpovede)

• Java Generics Interview otázky (+ odpovede)

• Otázky týkajúce sa riadenia toku Java (+ odpovede)

• Otázky týkajúce sa rozhovorov o výnimkách jazyka Java (+ odpovede)

• Dotazy k anotáciám Java (+ odpovede)

• Najlepšie otázky týkajúce sa jarného rámcového rozhovoru

1. Úvod

Java Collections je téma, o ktorej sa často diskutuje pri technických rozhovoroch pre vývojárov Java. V tomto článku sú uvedené niektoré dôležité otázky, ktoré sú kladené najčastejšie, a môže byť zložité ich napraviť.

2. Otázky

Q1. Popíšte hierarchiu typov zbierok. Aké sú hlavné rozhrania a aké sú medzi nimi rozdiely?

The Iterable rozhranie predstavuje ľubovoľnú kolekciu, ktorú je možné iterovať pomocou pre každý slučka. The Zbierka rozhranie dedí z Iterable a pridáva všeobecné metódy kontroly, či je prvok v kolekcii, pridávania a odstraňovania prvkov z kolekcie, určovania jeho veľkosti atď.

The Zoznam, Nastaviťa Fronta rozhrania dedia z Zbierka rozhranie.

Zoznam je usporiadaná kolekcia a k jej prvkom je možné získať prístup pomocou ich indexu v zozname.

Nastaviť je neusporiadaná kolekcia s výraznými prvkami, podobná matematickému poňatiu množiny.

Fronta je kolekcia s ďalšími metódami na pridávanie, odstraňovanie a skúmanie prvkov, ktorá je užitočná na uchovanie prvkov pred spracovaním.

Mapa rozhranie je tiež súčasťou zberného rámca, ale nerozširuje sa Zbierka. Toto je zámerné, zdôrazniť rozdiel medzi zbierkami a mapovaniami, ktoré je ťažké zhromaždiť pri bežnej abstrakcii. The Mapa rozhranie predstavuje dátovú štruktúru kľúč - hodnota s jedinečnými kľúčmi a s maximálne jednou hodnotou pre každý kľúč.

Q2. Popíšte rôzne implementácie mapového rozhrania a ich prípadové rozdiely.

Jedna z najčastejšie používaných implementácií Mapa rozhranie je HashMap. Je to typická štruktúra hašovacích máp, ktorá umožňuje prístup k prvkom v konštantnom čase, alebo O (1), ale nezachováva poriadok a nie je bezpečný pre vlákna.

Na zachovanie poradia vkladania prvkov môžete použiť LinkedHashMap trieda, ktorá rozširuje HashMap a navyše spojí prvky do prepojeného zoznamu s predvídateľnou réžiou.

The TreeMap trieda ukladá svoje prvky do červeno-čiernej stromovej štruktúry, ktorá umožňuje prístup k prvkom v logaritmickom čase, alebo O (log (n)). Je to pomalšie ako HashMap vo väčšine prípadov, ale podľa niektorých umožňuje udržiavať prvky v poriadku Komparátor.

The ConcurrentHashMap je implementácia hašovacej mapy bezpečná pre vlákna. Poskytuje úplnú súbežnosť vyhľadávaní (ako dostať operácia neznamená uzamknutie) a vysoko očakávanú súbežnosť aktualizácií.

The Hashtable trieda je v Jave od verzie 1.0. Nie je zastarané, ale väčšinou sa považuje za zastarané. Je to mapa hash bezpečná pre vlákna, ale na rozdiel od ConcurrentHashMap, všetky jeho metódy sú jednoducho synchronizované, čo znamená, že všetky operácie na tomto mapovom bloku, dokonca aj načítanie nezávislých hodnôt.

Q3. Vysvetlite rozdiel medzi Linkedlistom a Arraylistom.

ArrayList je implementácia Zoznam rozhranie, ktoré je založené na poli. ArrayList interne spracováva zmenu veľkosti tohto poľa, keď sú prvky pridané alebo odstránené. K jeho prvkom máte prístup v konštantnom čase pomocou ich indexu v poli. Vloženie alebo odstránenie prvku však odvodzuje posun všetkých následných prvkov, ktoré môžu byť pomalé, ak je pole obrovské a vložený alebo odstránený prvok je blízko začiatku zoznamu.

LinkedList je dvojnásobne prepojený zoznam: vkladajú sa jednotlivé prvky Uzol objekty, ktoré majú odkazy na predchádzajúce a nasledujúce Uzol. Táto implementácia sa môže javiť ako efektívnejšia ako ArrayList ak máte veľa vložení alebo odstránení v rôznych častiach zoznamu, najmä ak je zoznam veľký.

Vo väčšine prípadov však ArrayList prekonáva LinkedList. Rovnomerné posúvanie prvkov ArrayList, hoci je to operácia O (n), je implementovaná ako veľmi rýchla System.arraycopy () hovor. Môže sa dokonca javiť rýchlejšie ako LinkedListVkladanie O (1), ktoré si vyžaduje vytvorenie inštancie a Uzol objekt a aktualizácia viacerých referencií pod kapotou. LinkedList tiež môže mať veľkú réžiu pamäte v dôsledku vytvorenia viacerých malých Uzol predmety.

Q4. Aký je rozdiel medzi Hashsetom a Treesetom?

Oboje HashSet a TreeSet triedy implementujú Nastaviť rozhranie a predstavujú množiny odlišných prvkov. Navyše, TreeSet realizuje NavigableSet rozhranie. Toto rozhranie definuje metódy, ktoré využívajú usporiadanie prvkov.

HashSet je interne založený na a HashMapa TreeSet je podložená a TreeMap inštancia, ktorá definuje ich vlastnosti: HashSet neuchováva prvky v konkrétnom poradí. Iterácia prvkov v a HashSet ich vyrába v zamiešanom poradí. TreeSet, na druhej strane, vytvára prvky v poradí podľa niektorých preddefinovaných Komparátor.

Q5. Ako sa implementuje Hashmap v Jave? Ako sa pri jeho implementácii využívajú metódy objektov v tvare Hashcode a Equals? Aká je časová zložitosť kladenia a získavania prvkov z takejto štruktúry?

The HashMap trieda predstavuje typickú dátovú štruktúru hash máp s určitými návrhovými voľbami.

The HashMap je zálohované zmeniteľným poľom, ktoré má veľkosť sily dvoch. Keď je prvok pridaný do a HashMap, najskôr jeho hashCode sa počíta (an int hodnota). Potom sa určitý počet nižších bitov tejto hodnoty použije ako index poľa. Tento index priamo ukazuje na bunku poľa (nazývanú vedro), kde by mal byť umiestnený tento pár kľúč - hodnota. Prístup k prvku pomocou jeho indexu v poli je veľmi rýchla operácia O (1), ktorá je hlavnou vlastnosťou štruktúry hash mapy.

A hashCode nie je jedinečný, a dokonca ani pre rôzne hashCodes, môžeme dostať rovnakú pozíciu poľa. Tomu sa hovorí kolízia. Existuje viac ako jeden spôsob riešenia kolízií v dátových štruktúrach hash máp. V jazyku Java HashMap, každý segment sa v skutočnosti nevzťahuje na jeden objekt, ale na červeno-čierny strom všetkých objektov, ktoré pristáli v tomto segmente (pred jazykom Java 8 to bol prepojený zoznam).

Takže keď HashMap určil segment pre kľúč, musí tento strom prejsť, aby na jeho miesto vložil pár kľúč - hodnota. Ak pár s takýmto kľúčom už v skupine existuje, nahradí sa novým.

Ak chcete získať objekt pomocou jeho kľúča, stlačte HashMap opäť musí vypočítať hashCode pre kľúč nájdite príslušné vedro, prejdite stromom, zavolajte rovná sa na kľúčoch v strome a nájdite zodpovedajúcu.

HashMap má O (1) zložitosť alebo zložitosť v konštantnom čase, kladenie a získavanie prvkov. Samozrejme, veľa kolízií by mohlo v horšom prípade zhoršiť výkon na časovú zložitosť O (log (n)), keď všetky prvky pristanú v jednom vedre. To sa zvyčajne rieši poskytnutím dobrej hashovacej funkcie s rovnomerným rozdelením.

Keď HashMap vnútorné pole je vyplnené (viac v nasledujúcej otázke), automaticky sa zmení jeho veľkosť, aby bola dvakrát väčšia. Táto operácia vyvodzuje opätovné premiešanie (prestavba interných dátových štruktúr), ktoré je nákladné, takže by ste si mali naplánovať veľkosť HashMap vopred.

Q6. Aký je účel parametrov počiatočnej kapacity a koeficientu zaťaženia hašmapy? Aké sú ich predvolené hodnoty?

The initialCapacity argument HashMap konštruktor ovplyvňuje veľkosť vnútornej dátovej štruktúry súboru HashMap, ale uvažovanie o skutočnej veľkosti mapy je trochu zložité. The HashMapInterná dátová štruktúra je pole o sile dvoch. Takže initialCapacity hodnota argumentu sa zvýši na ďalšiu mocninu dvoch (napríklad ak nastavíte hodnotu 10, skutočná veľkosť vnútorného poľa bude 16).

Faktor zaťaženia a HashMap je pomer počtu prvkov vydelený počtom segmentov (t.j. veľkosť vnútorného poľa). Napríklad ak 16-vedierko HashMap obsahuje 12 prvkov, jeho záťažový faktor je 12/16 = 0,75. Vysoký faktor zaťaženia znamená veľa kolízií, čo zase znamená, že veľkosť mapy by sa mala zmeniť na ďalšiu mocninu dvoch. Takže vyťaženosť argument je maximálna hodnota koeficientu vyťaženia mapy. Keď mapa dosiahne tento faktor zaťaženia, zmení veľkosť vnútorného poľa na ďalšiu hodnotu dvoch mocnín.

The initialCapacity je predvolene 16 a loadFactor je predvolene 0,75, takže do a môžete vložiť 12 prvkov HashMap ktorý bol inštancovaný s predvoleným konštruktorom, a jeho veľkosť by sa nezmenila. To isté platí pre HashSet, za ktorým stojí a HashMap napríklad interne.

Preto nie je triviálne prísť s tým initialCapacity ktoré uspokoja vaše potreby. Preto má knižnica Guava Maps.newHashMapWithExectedSize () a Sets.newHashSetWithExpectedSize () metódy, ktoré vám umožňujú zostaviť a HashMap alebo a HashSet ktoré môžu obsahovať očakávaný počet prvkov bez zmeny veľkosti.

Q7. Popíšte špeciálne zbierky pre výčet. Aké sú výhody ich implementácie v porovnaní s bežnými zbierkami?

EnumSet a EnumMap sú špeciálne implementácie Nastaviť a Mapa zodpovedajúcim spôsobom. Tieto implementácie by ste mali vždy používať, keď máte do činenia s enummi, pretože sú veľmi účinné.

An EnumSet je len bitový vektor s „jednotkami“ v pozíciách zodpovedajúcich radovým hodnotám enumov prítomných v množine. Ak chcete skontrolovať, či je v sade hodnota enum, implementácia musí jednoducho skontrolovať, či je zodpovedajúci bit vo vektore „jeden“, čo je veľmi ľahká operácia. Podobne an EnumMap je pole prístupné s radovou hodnotou enum ako indexom. V prípade EnumMap, nie je potrebné počítať hašovacie kódy ani riešiť kolízie.

Q8. Aký je rozdiel medzi rýchlymi a bezpečnými iterátormi?

Iterátory pre rôzne kolekcie sú buď rýchle alebo bezpečné, v závislosti od toho, ako reagujú na súčasné úpravy. Súbežná modifikácia nie je len úpravou kolekcie z iného vlákna, ale aj úpravou z rovnakého vlákna, ale použitím iného iterátora alebo priamou úpravou kolekcie.

Rýchle zlyhanie iterátory (vrátené do HashMap, ArrayLista ďalšie kolekcie, ktoré nie sú bezpečné pre vlákna), iterujú cez internú dátovú štruktúru kolekcie a vrhajú sa ConcurrentModificationException akonáhle zistia súbežnú úpravu.

Bezpečné proti zlyhaniu iterátory (vrátené zbierkami bezpečnými pre vlákna, ako napr ConcurrentHashMap, CopyOnWriteArrayList) vytvoria kópiu štruktúry, na ktorú sa iterujú. Zaručujú bezpečnosť pri súčasných úpravách. Medzi ich nevýhody patrí nadmerná spotreba pamäte a iterácia nad pravdepodobne zastaranými údajmi v prípade, že bola kolekcia upravená.

Q9. Ako môžete použiť triedenie zbierok pomocou porovnateľných a porovnávacích rozhraní?

The Porovnateľné interface je rozhranie pre objekty, ktoré je možné porovnávať podľa určitého poradia. Jeho jediná metóda je porovnať s, ktorá pracuje na dvoch hodnotách: samotný objekt a objekt argumentu rovnakého typu. Napríklad Celé číslo, Dlhéa ďalšie číselné typy implementujú toto rozhranie. String tiež implementuje toto rozhranie a jeho porovnať s metóda porovnáva reťazce v lexikografickom poradí.

The Porovnateľné rozhranie umožňuje triediť zoznamy zodpovedajúcich objektov s Zbierka.sort () metóda a dodržať poradie iterácie v kolekciách, ktoré implementujú Zoradené a SortedMap. Ak je možné vaše objekty triediť pomocou nejakej logiky, mali by implementovať Porovnateľné rozhranie.

The Porovnateľné rozhranie sa zvyčajne implementuje pomocou prirodzeného usporiadania prvkov. Napríklad všetky Celé číslo čísla sú zoradené od menších po väčšie hodnoty. Niekedy však možno budete chcieť implementovať iný druh objednávania, napríklad zoradiť čísla v zostupnom poradí. The Komparátor tu môže pomôcť rozhranie.

Trieda objektov, ktoré chcete zoradiť, nemusí toto rozhranie implementovať. Jednoducho vytvoríte implementačnú triedu a definujete porovnaj metóda, ktorá prijíma dva objekty a rozhoduje o ich poradí. Potom môžete použiť inštanciu tejto triedy na potlačenie prirodzeného usporiadania Zbierka.sort () metóda alebo Zoradené a SortedMap inštancie.

Ako Komparátor interface je funkčné rozhranie, môžete ho nahradiť výrazom lambda, ako v nasledujúcom príklade. Zobrazuje zoradenie zoznamu pomocou prirodzeného zoradenia (Celé číslo‘S Porovnateľné rozhranie) a pomocou vlastného iterátora (Komparátor rozhranie).

List list1 = Arrays.asList (5, 2, 3, 4, 1); Zbierky.sort (zoznam1); assertEquals (nové celé číslo (1), list1.get (0)); List list1 = Arrays.asList (5, 2, 3, 4, 1); Zbierky.sort (zoznam1, (a, b) -> b - a); assertEquals (nové celé číslo (5), list1.get (0));
Ďalšie » Dotazy týkajúce sa systému Java Type

$config[zx-auto] not found$config[zx-overlay] not found