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.


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.


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());

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.


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.


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 .


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())

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 ...


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);  

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.




-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]

-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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.