Come copiare un file java.util.List in un altro java.util.List


135

Ho un oggetto List<SomeBean>popolato da un servizio Web. Voglio copiare / clonare il contenuto di tale elenco in un elenco vuoto dello stesso tipo. Una ricerca su Google per la copia di un elenco mi ha suggerito di utilizzare il Collections.copy()metodo. In tutti gli esempi che ho visto, l'elenco delle destinazioni doveva contenere il numero esatto di elementi per l'esecuzione della copia.

Poiché l'elenco che sto usando è popolato tramite un servizio web e contiene centinaia di oggetti, non posso usare la tecnica sopra. O lo sto usando male ?? !! Comunque, per farlo funzionare, ho provato a fare qualcosa del genere, ma ne ho ancora uno IndexOutOfBoundsException.

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

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

Ho provato a usare il wsListCopy=wsList.subList(0, wsList.size())ma ho avuto un ConcurrentAccessExceptionseguito nel codice. Hit e prova. :)

Comunque, la mia domanda è semplice, come posso copiare l'intero contenuto del mio elenco in un altro elenco? Non tramite iterazione, ovviamente.


11
Qualsiasi copia utilizzerà ovviamente l'iterazione. Puoi nasconderlo ma sarà ancora lì.
Peter Lawrey,

1
Prima di tutto: sei sicuro di dover copiare quell'elenco? Qual è la tua motivazione nel farlo?
ppeterka,

2
Sì, l'iterazione è semplicemente nascosta sotto quegli strati. Ma il commento è stato aggiunto per evitare risposte di iterazione. :)
Mono Jamoon

@ppeterka Sto eseguendo operazioni sulla lista, come removeAll (). In questo modo l'elenco perde i suoi dati originali. E "quei dati" sono anche richiesti in seguito.
Mono Jamoon

Qual è il tipo effettivo di un elenco, che viene restituito da app.allInOne(template)? ArrayList?
Andremoniy,

Risposte:


235

Usa questo:

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

Nota: non è ancora sicuro il thread, se si modifica otherListda un altro thread, è possibile che si desideri rendere tale otherList(e persino newList) un CopyOnWriteArrayList, ad esempio, oppure utilizzare una primitiva di blocco, come ReentrantReadWriteLock per serializzare l'accesso in lettura / scrittura a qualunque elenco sia accesso simultaneo.


1
Ora, mi sento davvero stupido :) Spero che costruirlo in questo modo non ne lanci nessuno ConcurrentAccessException.
Mono Jamoon


5
+1 se riceve ConcurrentModifcationException, ha un problema di concorrenza che deve risolvere per primo.
Peter Lawrey,

5
Perché questa risposta ottiene così tanti punti se la domanda menzionava "copia / clona"? Questo, purché alcune altre risposte non abbiano nulla a che fare con la clonazione. Gli stessi riferimenti verranno conservati per gli oggetti all'interno delle raccolte indipendentemente dai metodi di utilità specifici di raccolta / flusso utilizzati.
yuranos,

3
La risposta è sbagliata Il contenuto non viene copiato. Solo riferimenti.
L'incredibile gennaio

33

Questo è davvero un bel modo di Java 8 per farlo:

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

Naturalmente il vantaggio qui è che puoi filtrare e saltare solo alla copia di parte dell'elenco.

per esempio

//don't copy the first element 
List<String> list2 = list1.stream().skip(1).collect(Collectors.toList());

4
l'elenco risultante è una copia profonda o superficiale dell'elenco originale?
Ad Infinitum,

7
Una copia superficiale.
Kap il

3
Questo, purtroppo, non è sicuro per i thread. Supponendo che listvenga modificato mentre il raccoglitore è in esecuzione, ConcurrentModificationExceptionviene lanciato a.
C-Otto,

@Dan, Come saltare la copia dell'ultimo elemento?
CKM,

@chandresh per saltare la copia dell'ultimo elemento, useresti semplicemente.limit(list1.size() - 1)
Matthew Carpenter,

13
originalArrayList.addAll(copyArrayofList);

Tenere presente che ogni volta che si utilizza il metodo addAll () per la copia, i contenuti di entrambi gli elenchi di array (originalArrayList e copyArrayofList) verranno aggiunti all'elenco dei riferimenti agli stessi oggetti, quindi se si modifica uno di essi, anche copyArrayofList riflette lo stesso cambiamento.

Se non si desidera l'effetto collaterale, è necessario copiare ciascuno degli elementi dall'originaleArrayList in copyArrayofList, come utilizzare un ciclo for o while.


2
Questa è una delle poche vere Risposte qui, in quanto specifica #addAll fa una copia superficiale, oltre a come copiare in profondità. Maggiori informazioni: stackoverflow.com/questions/715650/...
cellepo

7

Ho provato a fare qualcosa del genere, ma ho ancora una IndexOutOfBoundsException.

Ho ottenuto una ConcurrentAccessException

Ciò significa che stai modificando l'elenco mentre stai provando a copiarlo, molto probabilmente in un altro thread. Per risolvere il problema devi farlo

  • utilizzare una raccolta progettata per l'accesso simultaneo.

  • bloccare la raccolta in modo appropriato in modo da poter iterare su di essa (o consentire di chiamare un metodo che lo fa per te)

  • trova una via per evitare di dover copiare l'elenco originale.


4

A partire da Java 10 :

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

List.copyOf()restituisce un non modificabile Listcontenente gli elementi del dato Collection.

Il dato Collectionnon deve essere nulle non deve contenere alcun nullelemento.

Inoltre, se vuoi creare una copia profonda di un List, puoi trovare molte buone risposte qui .


3

Esiste un altro metodo con Java 8 in modo null-safe.

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

Se vuoi saltare un elemento.

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

Con Java 9+, è possibile utilizzare il metodo stream di Opzionale

Optional.ofNullable(wsList)
    .stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList())

1

Avevo lo stesso problema ConcurrentAccessException e mysolution era:

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

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

Quindi funziona solo una operazione alla volta ed evita l'eccezione ...


1

Ho provato qualcosa di simile e sono stato in grado di riprodurre il problema (IndexOutOfBoundsException). Di seguito sono riportati i miei risultati:

1) L'implementazione di Collections.copy (destList, sourceList) controlla innanzitutto le dimensioni dell'elenco di destinazioni chiamando il metodo size (). Poiché la chiamata al metodo size () restituirà sempre il numero di elementi nell'elenco (0 in questo caso), il costruttore ArrayList (capacità) garantisce solo la capacità iniziale dell'array di supporto e questo non ha alcuna relazione con il dimensione dell'elenco. Quindi otteniamo sempre IndexOutOfBoundsException.

2) Un modo relativamente semplice è usare il costruttore che prende una collezione come argomento:

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);  

0

ri indexOutOfBoundsException:, la tua lista secondaria è il problema; è necessario terminare l'elenco secondario alla dimensione 1. Essendo a base zero, l'ultimo elemento di un elenco è sempre size-1, non vi è alcun elemento nella posizione size, quindi l'errore.




-2

Se non vuoi che le modifiche in un elenco abbiano effetto su un altro elenco, prova questo. Ha funzionato per me
Spero che questo aiuti.

  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

la funzione subList è un trucco, l'oggetto restituito è ancora nell'elenco originale. pertanto, se si esegue qualsiasi operazione in Elenco secondario, si verificherà l'eccezione simultanea nel codice, indipendentemente dal fatto che si tratti di thread singolo o multi thread.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.