Cara menyalin java.util.List ke java.util.List lain

135

Saya memiliki List<SomeBean>yang terisi dari Layanan Web. Saya ingin menyalin / mengkloning isi daftar itu ke daftar kosong dengan tipe yang sama. Pencarian Google untuk menyalin daftar menyarankan saya untuk menggunakan Collections.copy()metode. Dalam semua contoh yang saya lihat, daftar tujuan seharusnya berisi jumlah item yang tepat untuk penyalinan.

Karena daftar yang saya gunakan diisi melalui layanan web dan berisi ratusan objek, saya tidak dapat menggunakan teknik di atas. Atau saya salah menggunakannya !! Bagaimanapun, untuk membuatnya bekerja, saya mencoba melakukan sesuatu seperti ini, tetapi saya masih punya IndexOutOfBoundsException.

List<SomeBean> wsList = app.allInOne(template);

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList.size());   
Collections.copy(wsListCopy,wsList);
System.out.println(wsListCopy.size());

Saya mencoba menggunakan wsListCopy=wsList.subList(0, wsList.size())tetapi saya mendapat ConcurrentAccessExceptionkemudian dalam kode. Hit dan uji coba. :)

Bagaimanapun, pertanyaan saya sederhana, bagaimana saya bisa menyalin seluruh konten daftar saya ke Daftar lain? Bukan melalui iterasi, tentu saja.

Mono Jamoon
sumber
11
Setiap salinan tentu saja akan menggunakan iterasi. Anda dapat menyembunyikannya tetapi masih ada di sana.
Peter Lawrey
1
Pertama-tama: Anda yakin perlu menyalin daftar itu? Apa motivasi Anda dalam melakukan itu?
ppeterka
2
Yup, iterasi hanya disembunyikan di bawah lapisan itu. Tetapi komentar ditambahkan untuk mencegah jawaban iterasi. :)
Mono Jamoon
@ppeterka Saya melakukan operasi pada daftar, seperti removeAll (). Ini menyebabkan daftar kehilangan data aslinya. Dan "data itu" juga diperlukan setelahnya.
Mono Jamoon
Apa jenis sebenarnya dari daftar, yang dikembalikan oleh app.allInOne(template)? ArrayList?
Andremoniy

Jawaban:

235

Gunakan ini saja:

List<SomeBean> newList = new ArrayList<SomeBean>(otherList);

Catatan: masih tidak aman utas, jika Anda memodifikasi otherListdari utas lain, maka Anda mungkin ingin membuatnya otherList(dan bahkan newList) a CopyOnWriteArrayList, misalnya - atau menggunakan kunci primitif, seperti ReentrantReadWriteLock untuk membuat serial akses baca / tulis ke daftar apa pun yang ada diakses bersamaan.

Fge
sumber
1
Sekarang, saya hanya merasa sangat bodoh :) Saya berharap bahwa membangunnya seperti ini tidak akan membuang apa pun ConcurrentAccessException.
Mono Jamoon
5
+1 jika ia mendapatkan ConcurrentModifcationException, ia memiliki masalah konkurensi yang harus diperbaiki terlebih dahulu.
Peter Lawrey
5
Mengapa jawaban ini mendapatkan banyak poin jika pertanyaan menyebutkan "copy / clone"? Ini, selama beberapa jawaban lain tidak ada hubungannya dengan kloning. Referensi yang sama akan disimpan untuk objek di dalam koleksi apa pun koleksi / aliran metode utilitas khusus yang Anda gunakan.
yuranos
3
Jawabannya salah. Konten tidak disalin. Hanya referensi.
Jan
33

Ini adalah cara Java 8 yang sangat bagus untuk melakukannya:

List<String> list2 = list1.stream().collect(Collectors.toList());

Tentu saja keuntungannya di sini adalah Anda dapat memfilter dan melompat ke hanya menyalin sebagian dari daftar.

misalnya

//don't copy the first element 
List<String> list2 = list1.stream().skip(1).collect(Collectors.toList());
Dan
sumber
4
Apakah daftar yang dihasilkan merupakan salinan dalam atau dangkal dari daftar asli?
Ad Infinitum
7
Salinan dangkal.
kap
3
Sayangnya, ini juga tidak aman. Dengan asumsi listdiubah saat kolektor berjalan, a ConcurrentModificationExceptiondilemparkan.
C-Otto
@Dan, Cara melewati menyalin elemen terakhir?
CKM
@chandresh untuk melewati penyalinan elemen terakhir, Anda hanya akan menggunakan.limit(list1.size() - 1)
Matthew Carpenter
13
originalArrayList.addAll(copyArrayofList);

Harap diingat setiap kali menggunakan metode addAll () untuk menyalin, isi dari kedua daftar array (originalArrayList dan copyArrayofList) referensi ke objek yang sama akan ditambahkan ke daftar jadi jika Anda memodifikasi salah satu dari mereka maka copyArrayofList juga akan mencerminkan perubahan yang sama.

Jika Anda tidak ingin efek samping, maka Anda perlu menyalin setiap elemen dari originalArrayList ke copyArrayofList, seperti menggunakan for atau while.

Divyesh Kanzariya
sumber
2
Ini adalah salah satu dari beberapa Jawaban sejati di sini, karena ia menentukan #addAll membuat salinan yang dangkal, serta cara menyalin yang dalam. Keterangan lebih lanjut: stackoverflow.com/questions/715650/…
cellepo
7

Saya mencoba melakukan sesuatu seperti ini, tetapi saya masih mendapatkan IndexOutOfBoundsException.

Saya mendapat ConcurrentAccessException

Ini berarti Anda memodifikasi daftar saat Anda mencoba menyalinnya, kemungkinan besar di utas lainnya. Untuk memperbaikinya Anda harus melakukannya juga

  • menggunakan koleksi yang dirancang untuk akses bersamaan.

  • kunci koleksi dengan tepat sehingga Anda dapat mengulanginya (atau memungkinkan Anda memanggil metode yang melakukan ini untuk Anda)

  • temukan jalan untuk menghindari keharusan menyalin daftar asli.

Peter Lawrey
sumber
4

Mulai dari Jawa 10 :

List<E> oldList = List.of();
List<E> newList = List.copyOf(oldList);

List.copyOf()mengembalikan yang tidak dapat dimodifikasi yang Listmengandung unsur-unsur yang diberikanCollection .

Yang diberikan Collectiontidak boleh null, dan tidak boleh mengandung apa punnull elemen .

Juga, jika Anda ingin membuat salinan dalam List, Anda dapat menemukan banyak jawaban bagus di sini .

Oleksandr Pyrohov
sumber
3

Ada metode lain dengan Java 8 dengan cara null-safe.

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
    .map(Collection::stream)
    .orElseGet(Stream::empty)
    .collect(Collectors.toList());

Jika Anda ingin melewati satu elemen.

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
    .map(Collection::stream)
    .orElseGet(Stream::empty)
    .skip(1)
    .collect(Collectors.toList());

Dengan Java 9+, metode aliran Opsional dapat digunakan

Optional.ofNullable(wsList)
    .stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList())
Nicolas Henneaux
sumber
1

Saya mengalami masalah yang sama ConcurrentAccessException dan solusi saya adalah untuk:

List<SomeBean> tempList = new ArrayList<>();

for (CartItem item : prodList) {
  tempList.add(item);
}
prodList.clear();
prodList = new ArrayList<>(tempList);

Jadi itu hanya berfungsi satu operasi pada saat itu dan menghindari Pengecualian ...

T04435
sumber
1

Saya mencoba sesuatu yang serupa dan dapat mereproduksi masalah (IndexOutOfBoundsException). Di bawah ini adalah temuan saya:

1) Implementasi Collections.copy (destList, sourceList) pertama-tama memeriksa ukuran daftar tujuan dengan memanggil metode size (). Karena metode panggilan ke ukuran () akan selalu mengembalikan jumlah elemen dalam daftar (0 dalam kasus ini), konstruktor ArrayList (kapasitas) memastikan hanya kapasitas awal dari array dukungan dan ini tidak memiliki hubungan dengan ukuran daftar. Karenanya kami selalu mendapatkan IndexOutOfBoundsException.

2) Cara yang relatif sederhana adalah dengan menggunakan konstruktor yang mengambil koleksi sebagai argumennya:

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);  
Abhay Yadav
sumber
0

re indexOutOfBoundsException:, argumen sublist Anda adalah masalahnya; Anda harus mengakhiri sublist pada ukuran-1. Menjadi berbasis nol, elemen terakhir dari daftar selalu berukuran-1, tidak ada elemen dalam posisi ukuran, karenanya kesalahan.

Jon Nelson
sumber
0

Anda dapat menggunakan addAll ().

misalnya: wsListCopy.addAll(wsList);

samaludheen memberi tanda
sumber
0

Saya tidak dapat melihat jawaban yang benar. Jika Anda ingin salinan yang dalam, Anda harus mengulang dan menyalin objek secara manual (Anda dapat menggunakan copy constructor).

Jan yang luar biasa
sumber
Ini adalah salah satu dari beberapa Jawaban sejati di sini. Lebih detail: stackoverflow.com/questions/715650/…
cellepo
-2

Jika Anda tidak ingin perubahan dalam satu daftar untuk efek daftar lain coba ini. Ini bekerja untuk saya.
Semoga ini bisa membantu.

  public class MainClass {
  public static void main(String[] a) {

    List list = new ArrayList();
    list.add("A");

    List list2 = ((List) ((ArrayList) list).clone());

    System.out.println(list);
    System.out.println(list2);

    list.clear();

    System.out.println(list);
    System.out.println(list2);
  }
}

> Output:   
[A]  
[A]  
[]  
[A]
Aashis Shrestha
sumber
-3

Fungsi subList adalah trik, objek yang dikembalikan masih dalam daftar asli. jadi jika Anda melakukan operasi apa pun di subList, itu akan menyebabkan pengecualian bersamaan dalam kode Anda, tidak peduli itu satu utas atau multi utas.

weixingsun
sumber