Wie kann ich ein ArrayList
Element klonen und seine Elemente auch in Java klonen?
Zum Beispiel habe ich:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
Und ich würde erwarten, dass Objekte in clonedList
nicht die gleichen sind wie in der Hundeliste.
java
collections
clone
deep-copy
palig
quelle
quelle
Antworten:
Sie müssen die Elemente iterieren und einzeln klonen, wobei Sie die Klone im Verlauf in Ihr Ergebnisarray einfügen.
Damit dies funktioniert, müssen Sie natürlich Ihre
Dog
Klasse dazu bringen, dieCloneable
Schnittstelle zu implementieren und dieclone()
Methode zu überschreiben .quelle
Ich persönlich würde Dog einen Konstruktor hinzufügen:
Dann iterieren Sie einfach (wie in Varkhans Antwort gezeigt):
Ich finde, der Vorteil davon ist, dass Sie nicht mit dem kaputten Cloneable-Zeug in Java herumspielen müssen. Es entspricht auch der Art und Weise, wie Sie Java-Sammlungen kopieren.
Eine andere Möglichkeit könnte darin bestehen, eine eigene ICloneable-Schnittstelle zu schreiben und diese zu verwenden. Auf diese Weise können Sie eine generische Methode zum Klonen schreiben.
quelle
cloneList(List<Object>)
oderDog(Object)
?Alle Standardsammlungen verfügen über Kopierkonstruktoren. Benutze sie.
clone()
wurde mit mehreren Fehlern entworfen (siehe diese Frage ), daher ist es am besten, dies zu vermeiden.Ab Effective Java 2nd Edition , Punkt 11: Klon mit Bedacht überschreiben
Dieses Buch beschreibt auch die vielen Vorteile, die Kopierkonstruktoren gegenüber Cloneable / clone haben.
Betrachten Sie einen weiteren Vorteil der Verwendung von Kopierkonstruktoren: Angenommen, Sie haben eine
HashSet s
und möchten diese als kopierenTreeSet
. Die Klonmethode kann diese Funktionalität nicht bieten, ist jedoch mit einem Konvertierungskonstruktor einfach :new TreeSet(s)
.quelle
Java 8 bietet eine neue Möglichkeit, die Kopierkonstruktor- oder Klonmethode für die Elementhunde elegant und kompakt aufzurufen: Streams , Lambdas und Sammler .
Konstruktor kopieren:
Der Ausdruck
Dog::new
wird als Methodenreferenz bezeichnet . Es wird ein Funktionsobjekt erstellt, das einen Konstruktor aufruft, für den einDog
anderer Hund als Argument verwendet wird.Klonmethode [1]:
Ein Angebot
ArrayList
als ErgebnisOder wenn Sie eine Rückerstattung
ArrayList
benötigen (falls Sie diese später ändern möchten):Aktualisieren Sie die Liste
Wenn Sie den ursprünglichen Inhalt der
dogs
Liste nicht beibehalten müssen, können Sie stattdessen diereplaceAll
Methode verwenden und die Liste an Ort und Stelle aktualisieren:Alle Beispiele gehen davon aus
import static java.util.stream.Collectors.*;
.Sammler für
ArrayList
sDer Kollektor aus dem letzten Beispiel kann zu einer util-Methode gemacht werden. Da dies so häufig vorkommt, mag ich es persönlich, wenn es kurz und hübsch ist. So was:
[1] Hinweis zu
CloneNotSupportedException
:Damit diese Lösung funktioniert
clone
,Dog
darf die Methode von nicht deklarieren, dass sie ausgelöst wirdCloneNotSupportedException
. Der Grund ist, dass das Argument tomap
keine geprüften Ausnahmen auslösen darf.So was:
Dies sollte jedoch kein großes Problem sein, da dies ohnehin die beste Vorgehensweise ist. ( Effectice Java zum Beispiel gibt diesen Rat.)
Vielen Dank an Gustavo, der dies bemerkt hat.
PS:
Wenn Sie es schöner finden, können Sie stattdessen die Methodenreferenzsyntax verwenden, um genau dasselbe zu tun:
quelle
List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));
parallel
AufrufclonedDogs.add
von mehreren Threads gleichzeitig aufgerufen wird. Die verwendeten Versionencollect
sind threadsicher. Dies ist einer der Vorteile des Funktionsmodells der Stream-Bibliothek. Für parallele Streams kann derselbe Code verwendet werden.Unhandled exception type CloneNotSupportedException
aufd.clone()
. Das Deklarieren oder Abfangen der Ausnahme löst sie nicht.Dog
in diesem Beispiel), das Klonen nicht unterstützt. Sind Sie sicher, dass es dieClonable
Schnittstelle implementiert ?Grundsätzlich gibt es drei Möglichkeiten, ohne manuell zu iterieren:
1 Konstruktor verwenden
2 Verwenden von
addAll(Collection<? extends E> c)
3
addAll(int index, Collection<? extends E> c)
Methode mitint
Parameter verwendenHinweis: Das Verhalten dieser Vorgänge ist undefiniert, wenn die angegebene Sammlung während des Vorgangs geändert wird.
quelle
Ich denke, die aktuelle grüne Antwort ist schlecht , warum könnten Sie fragen?
Die Art und Weise, wie Serialisierung auch imo schlecht ist, müssen Sie möglicherweise überall Serializable hinzufügen.
Was ist die Lösung:
Java-Deep-Cloning-Bibliothek Die Cloning-Bibliothek ist eine kleine Open-Source-Java-Bibliothek (Apache-Lizenz), die Objekte tief klont. Die Objekte müssen die klonbare Schnittstelle nicht implementieren. Tatsächlich kann diese Bibliothek JEDE Java-Objekte klonen. Es kann verwendet werden, dh in Cache-Implementierungen, wenn Sie nicht möchten, dass das zwischengespeicherte Objekt geändert wird, oder wenn Sie eine tiefe Kopie von Objekten erstellen möchten.
Überprüfen Sie es unter https://github.com/kostaskougios/cloning
quelle
Ich habe einen Weg gefunden, Sie können json verwenden, um die Liste zu serialisieren / unserialisieren. Die serialisierte Liste enthält keinen Verweis auf das ursprüngliche Objekt, wenn unserialisiert.
Verwenden von gson:
Sie können dies auch mit Jackson und jeder anderen JSON-Bibliothek tun.
quelle
Ich habe diese Option immer verwendet:
quelle
Sie müssen das
ArrayList
von Hand klonen (indem Sie es durchlaufen und jedes Element in ein neues kopierenArrayList
), da diesclone()
nicht für Sie erledigt wird. Grund dafür ist, dass sich die in der enthaltenen ObjekteArrayList
möglicherweise nichtClonable
selbst implementieren .Edit : ... und genau das macht Varkhans Code.
quelle
Ein böser Weg ist es, es mit Reflexion zu tun. So etwas hat bei mir funktioniert.
quelle
original
Objekte verschiedener Klassen enthalten sind, wird dies meiner MeinungcloneMethod.invoke
nach mit einer Ausnahme fehlschlagen, wenn es mit der falschen Art von Objekt aufgerufen wird. Aus diesem Grund ist es möglicherweise besser,Method
für jedes Objekt einen bestimmten Klon abzurufen . Oder verwenden Sie die Klonmethode fürObject
(aber da diese geschützt ist, kann dies in mehreren Fällen fehlschlagen).Dadurch wird jeder Hund tief kopiert
quelle
Die anderen Poster sind korrekt: Sie müssen die Liste durchlaufen und in eine neue Liste kopieren.
Jedoch ... Wenn die Objekte in der Liste unveränderlich sind, müssen Sie sie nicht klonen. Wenn Ihr Objekt ein komplexes Objektdiagramm hat, müssen diese ebenfalls unveränderlich sein.
Der andere Vorteil der Unveränderlichkeit besteht darin, dass sie auch threadsicher sind.
quelle
Hier ist eine Lösung mit einem generischen Vorlagentyp:
quelle
Für Sie überschreiben Objekte die Methode clone ()
und rufen Sie .clone () für Vector obj oder ArraiList obj auf ....
quelle
Einfacher Weg mit commons-lang-2.3.jar diese Bibliothek von Java zum Klonen von Listen
Link herunterladen commons-lang-2.3.jar
Wie benutzt man
Ich hoffe dieser kann hilfreich sein.
: D.
quelle
Das Paket
import org.apache.commons.lang.SerializationUtils;
Es gibt eine Methode
SerializationUtils.clone(Object);
Beispiel
quelle
Ich habe gerade eine Bibliothek entwickelt, die ein Entitätsobjekt und ein java.util.List-Objekt klonen kann. Laden Sie einfach die JAR- Datei unter https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U herunter und verwenden Sie die statische Methode cloneListObject (Listenliste). Diese Methode klont nicht nur die Liste, sondern auch alle Entitätselemente.
quelle
Das Folgende hat bei mir funktioniert ..
in Dog.java
Hier wird die neue Liste, die mit der Methode createCopy erstellt wurde, über SerializationUtils.clone () erstellt. Änderungen an der neuen Liste wirken sich also nicht auf die ursprüngliche Liste aus
quelle
Ich denke, ich habe einen wirklich einfachen Weg gefunden, eine ArrayList mit tiefer Kopie zu erstellen. Angenommen, Sie möchten einen String ArrayList arrayA kopieren.
Lassen Sie mich wissen, wenn es bei Ihnen nicht funktioniert.
quelle