web-dev-qa-db-de.com

So kopieren Sie eine Java.util.List in eine andere Java.util.List

Ich habe einen List<SomeBean>, der von einem Webdienst ausgefüllt wird. Ich möchte den Inhalt dieser Liste in eine leere Liste desselben Typs kopieren/klonen. Bei einer Google-Suche nach dem Kopieren einer Liste wurde die Verwendung der Collections.copy()-Methode vorgeschlagen. In allen Beispielen, die ich gesehen habe, sollte die Zielliste genau die Anzahl der Elemente enthalten, die für das Kopieren verwendet werden sollen. 

Da die Liste, die ich verwende, über einen Webdienst ausgefüllt wird und Hunderte von Objekten enthält, kann ich die obige Technik nicht verwenden. Oder benutze ich es falsch? !! Damit das funktioniert, habe ich versucht, so etwas zu tun, aber ich habe trotzdem eine IndexOutOfBoundsException bekommen.

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

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

Ich habe versucht, die wsListCopy=wsList.subList(0, wsList.size()) zu verwenden, bekam jedoch später im Code ein ConcurrentAccessException. Hit und Probe. :)

Wie auch immer, meine Frage ist einfach: Wie kann ich den gesamten Inhalt meiner Liste in eine andere Liste kopieren? Natürlich nicht durch Iteration. 

108
Mono Jamoon

Verwenden Sie einfach dieses:

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

Hinweis: Immer noch nicht threadsicher. Wenn Sie otherList von einem anderen Thread aus ändern, möchten Sie beispielsweise otherList (und sogar newList) eine CopyOnWriteArrayList - oder ein Sperrelement wie ReentrantReadWriteLock verwenden um den Lese-/Schreibzugriff auf alle Listen zu serialisieren, auf die gleichzeitig zugegriffen wird.

206
fge

Dies ist eine wirklich schöne Java 8-Methode:

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

Der Vorteil hier ist natürlich, dass Sie filtern und überspringen können, um nur einen Teil der Liste zu kopieren.

z.B.

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

Denken Sie immer daran, wenn Sie die addAll () - Methode zum Kopieren verwenden. Der Inhalt der beiden Array-Listen (originalArrayList und copyArrayofList) auf die gleichen Objekte wird der Liste hinzugefügt. Wenn Sie also eine davon ändern, werden sie in die Liste aufgenommen copyArrayofList spiegelt auch die gleiche Änderung wider.

Wenn Sie keinen Nebeneffekt wünschen, müssen Sie jedes Element aus der originalArrayList in die copyArrayofList kopieren, beispielsweise eine for- oder while-Schleife.

8

Ich habe versucht, so etwas zu tun, bekam aber immer noch eine IndexOutOfBoundsException.

Ich habe eine ConcurrentAccessException erhalten 

Dies bedeutet, dass Sie die Liste ändern, während Sie versuchen, sie zu kopieren, höchstwahrscheinlich in einem anderen Thread. Um dies zu beheben, müssen Sie entweder 

  • verwenden Sie eine Sammlung, die für den gleichzeitigen Zugriff konzipiert ist. 

  • sperren Sie die Sammlung entsprechend, sodass Sie sie durchlaufen können (oder eine Methode aufrufen können, die dies für Sie erledigt).

  • suchen Sie ein Feld, um nicht die ursprüngliche Liste kopieren zu müssen.

7
Peter Lawrey

In Java 10:

List<T> newList = List.copyOf(oldList);

List.copyOf() gibt eine unveränderbare List zurück, die die Elemente der angegebenen Collection enthält.

Die angegebene Collection darf nicht null sein und darf keine null-Elemente enthalten.

2
Oleksandr

Es gibt eine andere Methode mit Java 8 auf nullsichere Weise.

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

Wenn Sie ein Element überspringen möchten.

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

Ich hatte das gleiche Problem ConcurrentAccessException und mysolution sollte:

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

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

Es funktioniert also nur eine Operation zur Zeit und vermeidet die Ausnahme ...

1
T04435

Ich habe etwas Ähnliches ausprobiert und konnte das Problem reproduzieren (IndexOutOfBoundsException). Hier sind meine Ergebnisse:

1) Die Implementierung von Collections.copy (destList, sourceList) überprüft zunächst die Größe der Zielliste, indem die size () -Methode aufgerufen wird. Da der Aufruf der size () - Methode immer die Anzahl der Elemente in der Liste zurückgibt (in diesem Fall 0), stellt der Konstruktor ArrayList (Kapazität) nur die anfängliche Kapazität des Backing-Arrays sicher und hat keine Beziehung zum Größe der Liste. Daher erhalten wir immer eine IndexOutOfBoundsException.

2) Ein relativ einfacher Weg ist die Verwendung des Konstruktors, der eine Collection als Argument verwendet:

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

Sie können addAll () verwenden.

zB: wsListCopy.addAll(wsList);

0

re: indexOutOfBoundsException, deine Unterlisten sind das Problem; Sie müssen die Unterliste auf size-1 beenden. Nullbasiert ist das letzte Element einer Liste immer size-1, es gibt kein Element in der Größenposition, daher der Fehler.

0
Jon Nelson

Ich kann keine richtige Antwort sehen. Wenn Sie eine tiefe Kopie wünschen, müssen Sie das Objekt manuell iterieren und kopieren (Sie können einen Kopierkonstruktor verwenden).

0