Soalan Temuduga Koleksi Java

Artikel ini adalah sebahagian daripada siri: • Pertanyaan Temuduga Koleksi Java (artikel semasa) • Soalan Temuduga Sistem Jenis Java

• Pertanyaan Temuduga Bersama Java (+ Jawapan)

• Soalan Temuduga Struktur dan Permulaan Kelas Java

• Soalan Temuduga Java 8 (+ Jawapan)

• Pengurusan Memori dalam Soalan Temuduga Java (+ Jawapan)

• Soalan Temuduga Generik Java (+ Jawapan)

• Soalan Temuduga Kawalan Aliran Java (+ Jawapan)

• Soalan Temuduga Pengecualian Java (+ Jawapan)

• Soalan Temuduga Anotasi Java (+ Jawapan)

• Soalan Temuduga Kerangka Musim Bunga Teratas

1. Pengenalan

Java Collections adalah topik yang sering dibahas dalam wawancara teknikal untuk pembangun Java. Artikel ini mengulas beberapa soalan penting yang paling kerap diajukan dan mungkin sukar untuk diperbaiki.

2. Soalan

S1. Huraikan Hierarki Jenis Koleksi. Apakah Antara Muka Utama, dan Apakah Perbezaan Antara Mereka?

The Iterable muka mewakili mana-mana koleksi yang boleh mengulangi menggunakan untuk-setiap gelung. The Collection mewarisi antara muka dari Iterable dan menambah kaedah umum untuk memeriksa jika unsur ini dalam koleksi, menambah dan membuang unsur-unsur dari pengumpulan, menentukan saiz dan lain-lain

The List , Set , dan Giliran muka mewarisi sebahagian Collection antara muka.

List adalah koleksi yang teratur, dan elemennya dapat diakses oleh indeks mereka dalam senarai.

Set adalah koleksi yang tidak tersusun dengan elemen yang berbeza, mirip dengan konsep matematik bagi satu set.

Queue adalah koleksi dengan kaedah tambahan untuk menambahkan, membuang dan memeriksa elemen, berguna untuk menahan elemen sebelum diproses.

Antaramuka peta juga merupakan bahagian dari kerangka pengumpulan, namun tidak memperluas Koleksi . Ini dengan reka bentuk, untuk menekankan perbezaan antara koleksi dan pemetaan yang sukar dikumpulkan di bawah pengabstrakan umum. The Peta muka mewakili struktur data-nilai utama dengan kekunci yang unik dan lebih daripada satu nilai tidak untuk setiap kekunci.

S2. Huraikan Pelbagai Pelaksanaan Antaramuka Peta dan Perbezaan Kes Penggunaannya.

Salah satu implementasi antara muka Peta yang paling sering digunakan ialah HashMap . Ini adalah struktur data peta hash khas yang membolehkan mengakses elemen dalam masa yang tetap, atau O (1), tetapi tidak mengekalkan ketertiban dan tidak selamat di dalam benang .

Untuk mengekalkan susunan elemen, anda boleh menggunakan kelas LinkedHashMap yang memperluas HashMap dan mengaitkan elemen ke dalam senarai yang dipautkan, dengan overhead yang dapat diramalkan.

The TreeMap kedai kelas unsur-unsur dalam struktur pokok merah-hitam, yang membolehkan unsur-unsur mengakses Masa logaritma, atau O (log (n)). Ini lebih perlahan daripada HashMap untuk kebanyakan kes, tetapi ia membolehkan elemen tetap tersusun menurut beberapa Perbandingan .

The ConcurrentHashMap adalah pelaksanaan peta hash yang selamat. Ini memberikan serentak pengambilan penuh (kerana operasi mendapatkan tidak memerlukan penguncian) dan jangkaan kemas kini yang diharapkan.

The Hashtable kelas telah di Jawa sejak versi 1.0. Ia tidak digunakan tetapi kebanyakannya dianggap usang. Ini adalah peta hash yang selamat untuk utas, tetapi tidak seperti ConcurrentHashMap , semua kaedahnya hanya diselaraskan , yang bermaksud bahawa semua operasi pada peta ini menyekat, bahkan mengambil nilai bebas.

S3. Terangkan Perbezaan Antara Senarai Terpaut dan Senarai Array.

ArrayList merupakan pelaksanaan Senarai antara muka yang berasaskan array. ArrayList secara dalaman menangani perubahan saiz array ini apabila elemen ditambahkan atau dikeluarkan. Anda boleh mengakses unsur-unsurnya dalam masa yang tetap dengan indeksnya dalam array. Walau bagaimanapun, memasukkan atau membuang elemen menggeser peralihan semua elemen seterusnya yang mungkin lambat jika susunannya besar dan elemen yang dimasukkan atau dikeluarkan hampir dengan awal senarai.

LinkedList adalah senarai dua kali ganda: elemen tunggal dimasukkan ke dalamobjek Node yang mempunyai rujukan ke Node sebelumnya dan seterusnya. Pelaksanaan ini mungkin kelihatan lebih efisien daripada ArrayList jika anda mempunyai banyak penyisipan atau penghapusan di bahagian yang berlainan dari senarai, terutamanya jika senarai itu besar.

Walau bagaimanapun, dalam kebanyakan kes, ArrayList mengatasi LinkedList . Malah elemen yang beralih dalam ArrayList , semasa menjadi operasi O (n), dilaksanakan sebagai panggilan System.arraycopy () yang sangat pantas . Ia bahkan boleh muncul lebih cepat daripada penyisipan OL (1) LinkedList yang memerlukan penentuan objek Node dan kemas kini pelbagai rujukan di bawah tudung. LinkedList juga boleh mempunyai memori besar yang besar kerana penciptaan beberapa objek Node kecil .

S4. Apakah Perbezaan antara Hashset dan Treeset?

Kedua-dua kelas HashSet dan TreeSet melaksanakan antara muka Set dan mewakili kumpulan elemen yang berbeza. Selain itu, TreeSet melaksanakan NavigableSet antara muka. Antara muka ini mentakrifkan kaedah yang memanfaatkan susunan elemen.

HashSet secara dalaman berdasarkan HashMap , dan TreeSet disokong oleh instance TreeMap , yang menentukan sifatnya: HashSet tidak menyimpan elemen dalam urutan tertentu. Pengulangan ke atas unsur-unsur dalam HashSet menghasilkannya dalam susunan acak. TreeSet , sebaliknya, menghasilkan unsur mengikut urutan menurut beberapa Perbandingan yang telah ditetapkan .

S5. Bagaimana Hashmap Dilaksanakan di Jawa? Bagaimana Pelaksanaannya Menggunakan Kaedah Hashcode dan Sama dengan Objek? Apakah Kerumitan Masa Meletakkan dan Mendapatkan Unsur dari Struktur tersebut?

The HashMap kelas mewakili struktur data peta hash tipikal dengan pilihan reka bentuk tertentu.

The HashMap disokong oleh pelbagai resizable yang mempunyai saiz kuasa kepada dua. Apabila elemen ditambahkan ke HashMap , pertama hashCode dikira ( nilai int ). Kemudian sebilangan bit yang lebih rendah dari nilai ini digunakan sebagai indeks tatasusunan. Indeks ini secara langsung menunjukkan sel array (disebut baldi) di mana pasangan nilai-kunci ini harus diletakkan. Mengakses elemen dengan indeksnya dalam array adalah operasi O (1) yang sangat cepat, yang merupakan ciri utama struktur peta hash.

A hashCode is not unique, however, and even for different hashCodes, we may receive the same array position. This is called a collision. There is more than one way of resolving collisions in the hash map data structures. In Java's HashMap, each bucket actually refers not to a single object, but to a red-black tree of all objects that landed in this bucket (prior to Java 8, this was a linked list).

So when the HashMap has determined the bucket for a key, it has to traverse this tree to put the key-value pair in its place. If a pair with such key already exists in the bucket, it is replaced with a new one.

To retrieve the object by its key, the HashMap again has to calculate the hashCode for the key, find the corresponding bucket, traverse the tree, call equals on keys in the tree and find the matching one.

HashMap has O(1) complexity, or constant-time complexity, of putting and getting the elements. Of course, lots of collisions could degrade the performance to O(log(n)) time complexity in the worst case, when all elements land in a single bucket. This is usually solved by providing a good hash function with a uniform distribution.

When the HashMap internal array is filled (more on that in the next question), it is automatically resized to be twice as large. This operation infers rehashing (rebuilding of internal data structures), which is costly, so you should plan the size of your HashMap beforehand.

Q6. What Is the Purpose of the Initial Capacity and Load Factor Parameters of a Hashmap? What Are Their Default Values?

The initialCapacity argument of the HashMap constructor affects the size of the internal data structure of the HashMap, but reasoning about the actual size of a map is a bit tricky. The HashMap‘s internal data structure is an array with the power-of-two size. So the initialCapacity argument value is increased to the next power-of-two (for instance, if you set it to 10, the actual size of the internal array will be 16).

The load factor of a HashMap is the ratio of the element count divided by the bucket count (i.e. internal array size). For instance, if a 16-bucket HashMap contains 12 elements, its load factor is 12/16 = 0.75. A high load factor means a lot of collisions, which in turn means that the map should be resized to the next power of two. So the loadFactor argument is a maximum value of the load factor of a map. When the map achieves this load factor, it resizes its internal array to the next power-of-two value.

The initialCapacity is 16 by default, and the loadFactor is 0.75 by default, so you could put 12 elements in a HashMap that was instantiated with the default constructor, and it would not resize. The same goes for the HashSet, which is backed by a HashMap instance internally.

Consequently, it is not trivial to come up with initialCapacity that satisfies your needs. This is why the Guava library has Maps.newHashMapWithExpectedSize() and Sets.newHashSetWithExpectedSize() methods that allow you to build a HashMap or a HashSet that can hold the expected number of elements without resizing.

Q7. Describe Special Collections for Enums. What Are the Benefits of Their Implementation Compared to Regular Collections?

EnumSet and EnumMap are special implementations of Set and Map interfaces correspondingly. You should always use these implementations when you're dealing with enums because they are very efficient.

An EnumSet is just a bit vector with “ones” in the positions corresponding to ordinal values of enums present in the set. To check if an enum value is in the set, the implementation simply has to check if the corresponding bit in the vector is a “one”, which is a very easy operation. Similarly, an EnumMap is an array accessed with enum's ordinal value as an index. In the case of EnumMap, there is no need to calculate hash codes or resolve collisions.

Q8. What Is the Difference Between Fail-Fast and Fail-Safe Iterators?

Iterators for different collections are either fail-fast or fail-safe, depending on how they react to concurrent modifications. The concurrent modification is not only a modification of collection from another thread but also modification from the same thread but using another iterator or modifying the collection directly.

Fail-fast iterators (those returned by HashMap, ArrayList, and other non-thread-safe collections) iterate over the collection's internal data structure, and they throw ConcurrentModificationException as soon as they detect a concurrent modification.

Fail-safe iterators (returned by thread-safe collections such as ConcurrentHashMap, CopyOnWriteArrayList) create a copy of the structure they iterate upon. They guarantee safety from concurrent modifications. Their drawbacks include excessive memory consumption and iteration over possibly out-of-date data in case the collection was modified.

Q9. How Can You Use Comparable and Comparator Interfaces to Sort Collections?

The Comparable interface is an interface for objects that can be compared according to some order. Its single method is compareTo, which operates on two values: the object itself and the argument object of the same type. For instance, Integer, Long, and other numeric types implement this interface. String also implements this interface, and its compareTo method compares strings in lexicographical order.

The Comparable interface allows to sort lists of corresponding objects with the Collections.sort() method and uphold the iteration order in collections that implement SortedSet and SortedMap. If your objects can be sorted using some logic, they should implement the Comparable interface.

The Comparable interface usually is implemented using natural ordering of the elements. For instance, all Integer numbers are ordered from lesser to greater values. But sometimes you may want to implement another kind of ordering, for instance, to sort the numbers in descending order. The Comparator interface can help here.

The class of the objects you want to sort does not need to implement this interface. You simply create an implementing class and define the compare method which receives two objects and decides how to order them. You may then use the instance of this class to override the natural ordering of the Collections.sort() method or SortedSet and SortedMap instances.

As the Comparator interface is a functional interface, you may replace it with a lambda expression, as in the following example. It shows ordering a list using a natural ordering (Integer‘s Comparable interface) and using a custom iterator (Comparator interface).

List list1 = Arrays.asList(5, 2, 3, 4, 1); Collections.sort(list1); assertEquals(new Integer(1), list1.get(0)); List list1 = Arrays.asList(5, 2, 3, 4, 1); Collections.sort(list1, (a, b) -> b - a); assertEquals(new Integer(5), list1.get(0));
Seterusnya » Soalan Temuduga Sistem Jenis Java