JavaRush /Blog Java /Random-MS /10 Soalan Teratas tentang Koleksi di Jawa
FedoraLinux
Tahap
Москва

10 Soalan Teratas tentang Koleksi di Jawa

Diterbitkan dalam kumpulan
Artikel tersebut ialah terjemahan artikel " 10 soalan teratas tentang Koleksi Java " . Di bawah ialah soalan paling popular tentang koleksi dalam Java, ditanya dan dibincangkan di Stackowerflow. Sebelum anda melihat soalan ini, adalah baik untuk melihat gambar rajah hierarki kelas. 1. Bila hendak menggunakan LinkedList dan bukannya ArrayList? ArrayList sebenarnya adalah tatasusunan; unsur-unsurnya boleh diakses secara langsung oleh indeks. Jika tatasusunan melimpah, yang baharu dengan lebih banyak ruang diperlukan. Meletakkan dan memindahkan semua elemen akan mengambil masa O(n). Selain itu, menambah dan mengalih keluar elemen adalah perlu untuk memindahkan elemen sedia ada dalam tatasusunan. Ini mungkin merupakan kesulitan terbesar menggunakan ArrayList. LinkedList ialah senarai berganda pautan elemen. Oleh itu, untuk mengakses elemen di tengah, anda perlu mencari dari awal hingga akhir helaian. Sebaliknya, menambah dan mengalih keluar elemen dalam LinkedList adalah lebih pantas kerana operasi ini hanya mengubah senarai itu sendiri. Masa terburuk dibandingkan di bawah:
Kaedah Senarai tatasusunan LinkedList
dapatkan(indeks) O(1) O(n)
tambah(E) O(n) O(1)
tambah(E, indeks) O(n) O(n)
keluarkan(indeks) O(n) O(n)
Iterator.remove() O(n) O(1)
Iterator.add(E) O(n) O(1)
Walaupun masa berjalan, penggunaan memori mesti dipertimbangkan secara individu untuk senarai besar. Dalam LinkedList, setiap nod mesti mempunyai sekurang-kurangnya dua penunjuk tambahan untuk memautkan nod sebelumnya dan seterusnya, manakala dalam ArrayList, hanya tatasusunan elemen diperlukan. Lebih banyak perbandingan senarai ArrayList, LinkedList dan Vector . 2. Setara yang cekap untuk mengalih keluar elemen semasa lelaran koleksi Satu-satunya cara yang betul untuk mengubah suai (mengalih keluar elemen) koleksi semasa lelaran ialah menggunakan Iterator.remove() . Contohnya: Ralat yang paling biasa ialah: Anda akan mendapat ConcurrentModificationException semasa menjalankan kod di atas. Ini berlaku kerana iterator dijana untuk bergerak melalui keseluruhan senarai, tetapi pada masa yang sama helaian ditukar dengan memanggil Iterator.remove(). Seperti yang ditulis dalam dokumentasi untuk pengecualian ini, Iterator itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); } for(Integer i: list) { list.remove(i); }
"secara amnya tidak dibenarkan untuk satu utas untuk mengubah suai koleksi manakala satu lagi thread sedang berulang ke atasnya."
Secara umum, satu utas tidak boleh diterima untuk mengubah suai koleksi semasa satu lagi utas melintasinya. 3. Bagaimana untuk menukar Senarai kepada tatasusunan int[]? Cara paling mudah untuk melakukan ini ialah menggunakan ArrayUtils , yang terletak di perpustakaan Apache Commons Lang . int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); Tiada jalan pintas untuk ungkapan ini dalam JDK. Ingat bahawa anda tidak boleh menggunakan List.toArray() kerana ungkapan ini menukarkan Senarai kepada Integer[] (yang bukan jenis primitif). Cara yang betul ialah pilihan berikut: int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); } 4. Bagaimana untuk menukar tatasusunan int[] kepada Senarai? Cara paling mudah juga ialah menggunakan ArrayUtils dalam perpustakaan Apache Commons Lang , seperti di atas. List list = Arrays.asList(ArrayUtils.toObject(array)); Juga, tiada jalan pintas untuk ungkapan ini dalam JDK. 5. Apakah cara terbaik untuk menapis koleksi? Anda boleh menggunakan pakej pihak ketiga seperti Guava atau Apache Commons Lang untuk meningkatkan fungsi. Kedua-dua pakej ini mempunyai kaedah penapis() (dalam kelas Collections2 daripada Guava dan CollectionUtils daripada Apache). Kaedah penapis() akan mengembalikan elemen yang sepadan dengan Predikat yang diberikan. Dalam JDK semuanya lebih rumit. Berita baiknya ialah predikat akan ditambah dalam Java 8 , tetapi buat masa ini anda perlu menggunakan Iterator untuk mengulangi keseluruhan koleksi. Sudah tentu, anda boleh meniru laluan yang diikuti oleh Guava dan Apache dengan membiasakan diri dengan antara muka Predikat baharu. Kini kita boleh menggunakan kod berikut untuk menapis koleksi: 6. Bagaimana untuk menukar Senarai kepada Set dengan mudah? Terdapat dua cara untuk melakukan ini, bergantung pada cara anda ingin mentakrifkan kesaksamaan. Sekeping kod pertama meletakkan senarai ke dalam HashSet. Pendua dalam kes ini ditentukan terutamanya oleh hashCode(). Biasanya ini akan berfungsi. Tetapi jika anda perlu mengambil kira laluan perbandingan, maka lebih baik menggunakan bahagian kedua kod, di mana anda boleh menentukan pembanding anda sendiri. 7. Bagaimanakah saya boleh mengalih keluar elemen pendua daripada ArrayList? Soalan ini agak berkaitan dengan soalan di atas. Jika susunan elemen dalam ArrayList tidak penting kepada anda, langkah bijak ialah meletakkan helaian dalam Set untuk mengalih keluar pendua, dan kemudian mengembalikannya semula ke Senarai. Di bawah adalah contoh. Jika susunan elemen penting kepada anda, maka pesanan itu boleh dipastikan dengan meletakkan senarai dalam LinkedHashSet , yang terdapat dalam JDK standard. 8. Koleksi yang disusun int[] array = {1,2,3,4,5}; List list = new ArrayList (); for(int i: array) { list.add(i); } Iterator itr = list.iterator(); while(itr.hasNext()) { int i = itr.next(); if (i > 5) { // filter all ints bigger than 5 itr.remove(); } } public interface Predicate { boolean test(T o); } public static void filter(Collection collection, Predicate predicate) { if ((collection != null) && (predicate != null)) { Iterator itr = collection.iterator(); while(itr.hasNext()) { T obj = itr.next(); if (!predicate.test(obj)) { itr.remove(); } } } } filter(list, new Predicate () { public boolean test(Integer i) { return i <= 5; } }); Set set = new HashSet (list); Set set = new TreeSet (aComparator); set.addAll(list); ArrayList** list = ... // initial a list with duplicate elements Set set = new HashSet (list); list.clear(); list.addAll(set); Terdapat beberapa cara untuk menyokong koleksi yang diisih dalam Java. Kesemuanya menyediakan koleksi dalam susunan semula jadi atau oleh pembanding tertentu. Dalam kes susunan semula jadi, anda juga perlu melaksanakan antara muka Sebanding pada elemen.
  1. Collections.sort() boleh mengisih Senarai. Seperti yang dinyatakan dalam dokumentasi Java, jenis ini adalah stabil dan menjamin prestasi n log(n).
  2. PriorityQueue menyediakan baris gilir yang teratur. Perbezaan antara PriorityQueue dan Collections.sort() ialah PriorityQueue mengekalkan susunan baris gilir sepanjang masa, tetapi anda hanya boleh mendapatkan elemen pertama baris gilir. Anda tidak boleh mengakses elemen secara rawak seperti PriorityQueue.get(4).
  3. Jika tiada pendua dalam koleksi, anda boleh memilih TreeSet . Juga seperti PriorityQueue, TreeSet mengekalkan set tersusun pada setiap masa. Anda boleh mendapatkan elemen terkecil atau terbesar daripada TreeSet, tetapi anda masih tidak boleh mempunyai akses rawak kepada elemen.
Ringkasnya, Collections.sort() menyediakan senarai pesanan sekali sahaja. PriorityQueue dan TreeSet mengekalkan koleksi tersusun pada setiap masa, dengan kos kekurangan akses terindeks kepada elemen. 9. Collections.emptyList() atau contoh baharu Soalan yang sama digunakan untuk emptyMap() dan emptySet(). Kedua-dua kaedah mengembalikan senarai kosong, tetapi Collections.emptyList() ialah senarai yang tidak boleh diubah. Ini bermakna anda tidak boleh menambah elemen baharu pada senarai "kosong". Di latar belakang, setiap panggilan ke kaedah Collections.emptyList() sebenarnya tidak mencipta contoh baharu senarai kosong. Sebaliknya, ia akan menggunakan semula contoh kosong yang sedia ada. Jika anda biasa dengan Singleton sebagai corak reka bentuk , anda harus memahami apa yang dimaksudkan. Ini sepatutnya memberi anda prestasi yang lebih baik jika dipanggil dengan kerap. 10 Menyalin koleksi, Collections.copy() Terdapat dua cara untuk menyalin senarai sumber ke senarai destinasi. Satu cara ialah menggunakan pembina ArrayList. Cara lain ialah menggunakan kaedah Collections.copy() . Perhatikan baris pertama: kami memperuntukkan senarai yang sekurang-kurangnya sepanjang panjang senarai asal, kerana dokumentasi Java tentang koleksi berkata: ArrayList dstList = new ArrayList (srcList);
Senarai destinasi mestilah sekurang-kurangnya sama dengan senarai sumber.
Ini bermakna senarai akhir mestilah tidak lebih pendek daripada yang asal. Kedua-dua kaedah adalah penyalinan cetek. Jadi apakah perbezaan antara kedua-dua kaedah ini? Pertama, Collections.copy() tidak akan mengagihkan semula kapasiti pengumpulan dstList, walaupun dstList tidak mempunyai ruang yang mencukupi untuk mengandungi semua elemen daripada srcList. Sebaliknya, ia akan membuang IndexOutOfBoundsException . Seseorang mungkin bertanya sama ada terdapat faedah untuk ini. Sebabnya ialah ini memastikan kaedah berjalan secara linear dalam masa. Ini juga sesuai apabila anda ingin menggunakan semula tatasusunan dan bukannya memperuntukkan semula memori dalam pembina ArrayList. Daripada kesimpulan Jika selepas membaca artikel anda masih mempunyai soalan, jangan ragu untuk bertanya kepada mereka dalam komen. Juga, jika anda mendapati sebarang ketidaktepatan dalam terjemahan atau sebarang kesilapan lain, kemudian tulis kepada PM, ia akan diperbetulkan, dan anda akan berterima kasih. Asal. ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList);
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION