Saya punya ArrayList
dan ingin menyalinnya dengan tepat. Saya menggunakan kelas utilitas bila mungkin dengan asumsi bahwa seseorang menghabiskan waktu untuk memperbaikinya. Jadi secara alami, saya berakhir dengan Collections
kelas yang berisi metode salin.
Misalkan saya memiliki yang berikut ini:
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b,a);
Ini gagal karena pada dasarnya itu dianggap b
tidak cukup besar untuk dipegang a
. Ya saya tahu b
memiliki ukuran 0, tetapi harus cukup besar sekarang bukan? Jika saya harus mengisi b
dulu, maka Collections.copy()
menjadi fungsi yang sama sekali tidak berguna dalam pikiran saya. Jadi, kecuali untuk pemrograman fungsi salinan (yang akan saya lakukan sekarang) apakah ada cara yang tepat untuk melakukan ini?
java
list
collections
copy
Lantai Jasper
sumber
sumber
Jawaban:
Panggilan
membuat salinan dangkal dari
a
dalamb
. Semua elemen akan adab
di dalam urutan yang sama persis dengan yang ada di dalamnyaa
(dengan asumsi itu memiliki pesanan)Begitu pula panggilan
juga membuat salinan dangkal dari
a
dalamb
. Jika parameter pertama,,b
tidak memiliki kapasitas yang cukup (bukan ukuran) untuk memuat semuaa
elemen, maka ia akan melemparIndexOutOfBoundsException
. Harapannya adalah bahwa tidak ada alokasi yang diperlukanCollections.copy
untuk bekerja, dan jika ada, maka itu melempar pengecualian itu. Ini merupakan pengoptimalan yang mengharuskan koleksi yang telah disalin dialokasikan sebelumnya (b
), tetapi saya biasanya tidak berpikir bahwa fitur ini sepadan karena pemeriksaan yang diperlukan mengingat alternatif berbasis konstruktor seperti yang ditunjukkan di atas yang tidak memiliki efek samping yang aneh.Untuk membuat salinan dalam
List
, melalui mekanisme mana pun, harus memiliki pengetahuan yang rumit tentang tipe yang mendasarinya. Dalam kasusString
s, yang tidak dapat diubah di Java (dan .NET dalam hal ini), Anda bahkan tidak memerlukan salinan yang dalam. Dalam hal iniMySpecialObject
, Anda perlu tahu cara membuat salinan yang dalam dan itu bukan operasi generik.Catatan: Jawaban yang awalnya diterima adalah hasil teratas untuk
Collections.copy
di Google, dan itu salah seperti yang ditunjukkan dalam komentar.sumber
b
memiliki kapasitas 3, tetapi ukuran 0. Fakta yangArrayList
memiliki semacam kapasitas buffer adalah detail implementasi - ini bukan bagian dariList
antarmuka, jadiCollections.copy(List, List)
jangan gunakan. Akan jelek untuk itu untuk kasus khususArrayList
.Seperti yang ditunjukkan oleh MrWiggles, menggunakan konstruktor ArrayList yang mengambil koleksi adalah cara untuk contoh yang disediakan.
Untuk skenario yang lebih rumit (yang mungkin menyertakan kode asli Anda), Anda dapat menemukan koleksi dalam Guava berguna.
sumber
Kerjakan saja:
ArrayList memiliki konstruktor yang akan menerima Koleksi lain untuk menyalin elemen dari
sumber
String
objek tidak berubah.Jawaban oleh Stephen Katulka (jawaban yang diterima) salah (bagian kedua). Ini menjelaskan bahwa
Collections.copy(b, a);
salinan yang dalam, yang tidak. Keduanya,new ArrayList(a);
danCollections.copy(b, a);
hanya melakukan salinan dangkal. Perbedaannya adalah, bahwa konstruktor mengalokasikan memori baru, dancopy(...)
tidak, yang membuatnya cocok dalam kasus di mana Anda dapat menggunakan kembali array, karena memiliki keunggulan kinerja di sana.API standar Java mencoba untuk mencegah penggunaan salinan dalam, karena akan buruk jika coders baru akan menggunakannya secara teratur, yang mungkin juga menjadi salah satu alasan mengapa
clone()
tidak publik secara default.Kode sumber untuk
Collections.copy(...)
dapat dilihat pada baris 552 di: http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/Collections-Jar-Zip-Logging-regex/java/util/ Collections.java.htmJika Anda membutuhkan salinan yang dalam, Anda harus mengulang item secara manual, menggunakan for for dan clone () pada setiap objek.
sumber
cara paling sederhana untuk menyalin Daftar adalah dengan mengirimkannya ke konstruktor daftar baru:
b
akan menjadi salinan dangkala
Melihat sumber
Collections.copy(List,List)
(saya belum pernah melihatnya) tampaknya untuk mengatasi elemen indeks dengan indeks. menggunakanList.set(int,E)
elemen 0 sehingga akan menulis elemen 0 di daftar target dll. Tidak terlalu jelas dari javadocs saya harus mengakui.sumber
tidak mengatur ukuran. Ini menetapkan kapasitas awal (menjadi berapa banyak elemen yang dapat ditampungnya sebelum perlu mengubah ukuran). Cara penyalinan yang lebih sederhana dalam hal ini adalah:
sumber
Sebagai hoijui menyebutkan. Jawaban yang dipilih dari Stephen Katulka berisi komentar tentang Collections.copy yang tidak benar. Penulis mungkin menerimanya karena baris kode pertama melakukan copy yang dia inginkan. Panggilan tambahan ke Collections.copy hanya menyalin lagi. (Menghasilkan salinan terjadi dua kali).
Ini kode untuk membuktikannya.
sumber
Sebagian besar jawaban di sini tidak menyadari masalah, pengguna ingin memiliki COPY elemen dari daftar pertama ke daftar kedua, elemen daftar tujuan adalah objek baru dan tidak merujuk ke elemen daftar asli. (Berarti mengubah elemen daftar kedua tidak boleh mengubah nilai untuk elemen yang sesuai dari daftar sumber.) Untuk objek yang dapat diubah kita tidak dapat menggunakan konstruktor ArrayList (Koleksi) karena itu akan sederhana merujuk ke elemen daftar asli dan tidak akan menyalin. Anda harus memiliki daftar cloner untuk setiap objek saat menyalin.
sumber
Mengapa Anda tidak menggunakan
addAll
metode saja:bahkan jika Anda memiliki item yang ada di b atau Anda ingin menunggu beberapa elemen setelahnya, seperti:
sumber
Jika Anda ingin menyalin ArrayList, salin dengan menggunakan:
sumber
String dapat disalin dengan mendalam
karena mereka tidak berubah. Setiap Objek lain tidak -> Anda perlu mengulang dan melakukan salinan sendiri.
sumber
b
menunjuk ke objek yang samaString
di dalamnyaa
. Namun, ini tidak penting karena, seperti yang Anda tunjukkan,String
objek tidak berubah.sumber
Setiap Objek lain tidak -> Anda perlu mengulang dan melakukan salinan sendiri.
Untuk menghindari ini menerapkan Cloneable.
....
sumber
Output berikut menggambarkan hasil menggunakan copy constructor dan Collections.copy ():
Sumber program lengkap ada di sini: Daftar Java copy . Tetapi hasilnya cukup untuk melihat bagaimana java.util.Collections.copy () berperilaku.
sumber
Dan jika Anda menggunakan google jambu, solusi satu baris adalah
Ini membuat instance daftar array yang dapat diubah.
sumber
Dengan Java 8 menjadi null-safe, Anda bisa menggunakan kode berikut.
Atau menggunakan kolektor
sumber
Salin tidak berguna jika Anda membayangkan use case untuk menyalin beberapa nilai ke dalam koleksi yang ada. Yaitu Anda ingin menimpa elemen yang sudah ada alih-alih menyisipkan.
Contoh: a = [1,2,3,4,5] b = [2,2,2,2,3,3,3,3,4,4,4,] a.copy (b) = [1,2,3,4,5,3,3,3,3,4,4,4]
Namun saya mengharapkan metode salin yang akan mengambil parameter tambahan untuk indeks awal pengumpulan sumber dan target, serta parameter untuk penghitungan.
Lihat Java BUG 6350752
sumber
Untuk memahami mengapa Collections.copy () melempar IndexOutOfBoundsException meskipun Anda telah membuat array dukungan daftar tujuan cukup besar (melalui ukuran () pada sourceList), lihat jawaban oleh Abhay Yadav dalam pertanyaan terkait ini: Cara salin java.util.List ke java.util.List lain
sumber