Artikel tersebut merupakan terjemahan dari artikel
" 10 pertanyaan teratas tentang Koleksi Java " . Di bawah ini adalah pertanyaan paling populer tentang koleksi di Java, yang ditanyakan dan didiskusikan di Stackowerflow. Sebelum Anda melihat pertanyaan-pertanyaan ini, ada baiknya melihat diagram hierarki kelas.
1. Kapan menggunakan LinkedList dan bukan ArrayList?
ArrayList sebenarnya adalah sebuah array; elemen-elemennya dapat diakses langsung dengan indeks. Jika array meluap, diperlukan array baru dengan lebih banyak ruang. Menempatkan dan memindahkan semua elemen akan memakan waktu O(n). Selain itu, penambahan dan penghapusan elemen diperlukan untuk memindahkan elemen yang ada dalam array. Ini mungkin ketidaknyamanan terbesar dalam menggunakan ArrayList. LinkedList adalah daftar ganda tautan elemen. Jadi, untuk mengakses elemen di tengah, Anda harus mencari dari awal hingga akhir lembar. Di sisi lain, menambah dan menghapus elemen dalam LinkedList lebih cepat karena operasi ini hanya mengubah daftar itu sendiri. Saat-saat terburuk dibandingkan di bawah ini:
metode |
Daftar susunan |
Daftar Tertaut |
dapatkan (indeks) |
HAI(1) |
Pada) |
tambahkan (E) |
Pada) |
HAI(1) |
tambahkan(E, indeks) |
Pada) |
Pada) |
hapus (indeks) |
Pada) |
Pada) |
Iterator.hapus() |
Pada) |
HAI(1) |
Iterator.tambahkan(E) |
Pada) |
HAI(1) |
Meskipun waktu berjalan, penggunaan memori harus dipertimbangkan secara individual untuk daftar besar. Dalam LinkedList, setiap node harus memiliki setidaknya dua pointer tambahan untuk menghubungkan node sebelumnya dan berikutnya, sedangkan dalam ArrayList, hanya diperlukan array elemen. Lebih banyak perbandingan
daftar ArrayList, LinkedList dan Vector .
2. Setara yang efisien untuk menghapus elemen selama iterasi koleksi Satu-satunya cara yang benar untuk memodifikasi (menghapus elemen) koleksi selama iterasi adalah dengan menggunakan
Iterator.remove() . Misalnya: Kesalahan paling umum adalah: Anda akan mendapatkan
ConcurrentModificationException saat menjalankan kode di atas. Hal ini terjadi karena iterator dibuat untuk berpindah ke seluruh daftar, namun pada saat yang sama sheet diubah dengan memanggil Iterator.remove(). Seperti yang tertulis dalam dokumentasi untuk pengecualian ini,
Iterator
itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); }
for(Integer i: list) { list.remove(i); }
"umumnya tidak diperbolehkan bagi satu thread untuk memodifikasi koleksi sementara thread lain mengulanginya."
Secara umum, tidak dapat diterima jika satu thread memodifikasi koleksi sementara thread lain melintasinya.
3. Bagaimana cara mengubah array Daftar menjadi int[]? Cara termudah untuk melakukannya adalah dengan menggunakan
ArrayUtils , yang terletak di perpustakaan
Apache Commons Lang .
int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));
Tidak ada jalan pintas untuk ekspresi ini di JDK. Ingatlah bahwa Anda tidak dapat menggunakan List.toArray() karena ekspresi ini mengonversi List menjadi Integer[] (yang
bukan merupakan tipe primitif). Cara yang benar adalah dengan opsi berikut:
int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); }
4. Bagaimana cara mengubah array int[] menjadi Daftar? Cara termudah juga adalah dengan menggunakan
ArrayUtils di perpustakaan
Apache Commons Lang , seperti di atas.
List list = Arrays.asList(ArrayUtils.toObject(array));
Selain itu, tidak ada jalan pintas untuk ekspresi ini di JDK.
5. Apa cara terbaik untuk memfilter koleksi? Anda dapat menggunakan paket pihak ketiga seperti
Guava atau
Apache Commons Lang untuk meningkatkan fungsionalitas. Kedua paket ini memiliki metode filter() (di kelas
Collections2 dari Guava dan
CollectionUtils dari Apache). Metode filter() akan mengembalikan elemen yang cocok dengan Predikat yang diberikan. Di JDK semuanya lebih rumit. Kabar baiknya adalah predikat akan ditambahkan di Java 8
, tetapi untuk saat ini Anda perlu menggunakan Iterator untuk melakukan iterasi ke seluruh koleksi. Tentu saja, Anda dapat meniru jalur yang diikuti oleh Guava dan Apache dengan mengenal antarmuka Predicate yang baru. Sekarang kita dapat menggunakan kode berikut untuk memfilter koleksi:
6. Bagaimana cara mudah mengubah Daftar ke Kumpulan? Ada dua cara untuk melakukan hal ini, bergantung pada bagaimana Anda ingin mendefinisikan kesetaraan. Potongan kode pertama memasukkan daftar ke dalam HashSet. Duplikat dalam hal ini ditentukan terutama oleh kode hash(). Biasanya ini akan berhasil. Namun jika Anda perlu memperhitungkan jalur perbandingan, akan lebih baik jika menggunakan bagian kedua dari kode, di mana Anda dapat menentukan pembanding Anda sendiri.
7. Bagaimana cara menghapus elemen duplikat dari ArrayList? Pertanyaan ini agak berkaitan dengan pertanyaan di atas. Jika urutan elemen dalam ArrayList tidak menjadi masalah bagi Anda, langkah cerdas adalah menempatkan sheet dalam Set untuk menghapus duplikat, dan kemudian mengembalikannya ke Daftar. Di bawah ini adalah contohnya. Jika urutan elemen penting bagi Anda, maka urutannya dapat dipastikan dengan menempatkan daftar di
LinkedHashSet , yang ada di JDK standar.
8. Koleksi yang diurutkan
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);
Ada beberapa cara untuk mendukung koleksi yang diurutkan di Java. Semuanya menyediakan koleksi dalam tatanan alami atau dengan pembanding tertentu. Dalam kasus tatanan alami, Anda juga perlu mengimplementasikan antarmuka
Comparable pada elemen tersebut.
- Collections.sort() dapat mengurutkan Daftar. Sebagaimana dinyatakan dalam dokumentasi Java, pengurutan ini stabil dan menjamin kinerja n log(n).
- PriorityQueue menyediakan antrian yang teratur. Perbedaan antara PriorityQueue dan Collections.sort() adalah PriorityQueue mempertahankan urutan antrian sepanjang waktu, namun Anda hanya bisa mendapatkan elemen pertama dari antrian. Anda tidak dapat mengakses elemen seperti PriorityQueue.get(4) secara acak.
- Jika tidak ada duplikat dalam koleksi, Anda dapat memilih TreeSet . Juga seperti PriorityQueue, TreeSet mempertahankan kumpulan yang terurut setiap saat. Anda bisa mendapatkan elemen terkecil atau terbesar dari TreeSet, tetapi Anda tetap tidak dapat memiliki akses acak ke elemen tersebut.
Sederhananya, Collections.sort() menyediakan daftar pesanan satu kali. PriorityQueue dan TreeSet mempertahankan koleksi yang terurut setiap saat, dengan mengorbankan kurangnya akses yang diindeks ke elemen.
9. Collections.emptyList() atau instance baru Pertanyaan yang sama berlaku untuk blankMap() dan blankSet(). Kedua metode mengembalikan daftar kosong, tetapi Collections.emptyList() adalah daftar yang tidak dapat diubah. Ini berarti Anda
tidak dapat menambahkan elemen baru ke daftar "kosong". Di latar belakang, setiap panggilan ke metode Collections.emptyList() sebenarnya tidak membuat instance baru dari daftar kosong. Sebaliknya, ia akan menggunakan kembali instance kosong yang sudah ada. Jika Anda sudah familiar dengan Singleton sebagai pola
desain , Anda pasti mengerti apa yang dimaksud. Ini akan memberi Anda kinerja
yang lebih baik jika sering dipanggil.
10 Menyalin koleksi, Collections.copy() Ada dua cara untuk menyalin daftar sumber ke daftar tujuan. Salah satu caranya adalah dengan menggunakan konstruktor ArrayList. Cara lainnya adalah dengan menggunakan metode
Collections.copy() . Perhatikan pada baris pertama: kami mengalokasikan daftar yang panjangnya setidaknya sama dengan panjang daftar asli, karena dokumentasi Java tentang koleksi mengatakan:
ArrayList
dstList = new ArrayList
(srcList);
Daftar tujuan setidaknya harus sepanjang daftar sumber.
Artinya, daftar akhir tidak boleh lebih pendek dari daftar aslinya. Kedua metode ini merupakan penyalinan yang dangkal. Lalu apa perbedaan kedua metode ini? Pertama, Collections.copy() tidak akan mengalokasikan ulang kapasitas koleksi dstList, meskipun dstList tidak memiliki cukup ruang untuk memuat semua elemen dari srcList. Sebaliknya, ia akan memunculkan
IndexOutOfBoundsException . Mungkin ada yang bertanya apakah ada manfaatnya. Alasannya adalah hal ini memastikan bahwa metode berjalan secara linear dalam waktu. Ini juga cocok bila Anda ingin menggunakan kembali array daripada mengalokasikan ulang memori di konstruktor ArrayList.
Daripada menyimpulkan Jika setelah membaca artikel Anda masih memiliki pertanyaan, silakan tanyakan di kolom komentar. Juga, jika Anda menemukan ketidakakuratan dalam terjemahan atau kesalahan lainnya, tulislah ke PM, itu akan diperbaiki, dan Anda akan berterima kasih.
Asli.
ArrayList
dstList = new ArrayList
(srcList.size()); Collections.copy(dstList, srcList);
GO TO FULL VERSION