Comment puis-je cloner un ArrayList
et également cloner ses éléments en Java?
Par exemple, j'ai:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
Et je m'attendrais à ce que les objets clonedList
ne soient pas les mêmes que dans la liste des chiens.
java
collections
clone
deep-copy
palig
la source
la source
Réponses:
Vous devrez parcourir les éléments et les cloner un par un, en plaçant les clones dans votre tableau de résultats au fur et à mesure.
Pour que cela fonctionne, évidemment, vous devrez demander à votre
Dog
classe d'implémenter l'Cloneable
interface et de remplacer laclone()
méthode.la source
Personnellement, j'ajouterais un constructeur à Dog:
Ensuite, répétez (comme indiqué dans la réponse de Varkhan):
Je trouve que l'avantage est que vous n'avez pas besoin de faire le tour avec les trucs clonables cassés en Java. Il correspond également à la façon dont vous copiez les collections Java.
Une autre option pourrait être d'écrire votre propre interface ICloneable et de l'utiliser. De cette façon, vous pourriez écrire une méthode générique pour le clonage.
la source
cloneList(List<Object>)
ouDog(Object)
?Toutes les collections standard ont des constructeurs de copie. Utilise les.
clone()
a été conçu avec plusieurs erreurs (voir cette question ), il est donc préférable de l'éviter.Extrait de Effective Java 2nd Edition , Item 11: Override clone judiciously
Ce livre décrit également les nombreux avantages des constructeurs de copie par rapport à Cloneable / clone.
Considérez un autre avantage de l'utilisation des constructeurs de copie: supposons que vous ayez un
HashSet s
et que vous souhaitiez le copier en tant queTreeSet
. La méthode clone ne peut pas offrir cette fonctionnalité, mais il est facile avec un constructeur de conversion:new TreeSet(s)
.la source
Java 8 fournit une nouvelle façon d'appeler le constructeur de copie ou la méthode de clonage sur les chiens d'élément de manière élégante et compacte: Streams , lambdas et collectors .
Constructeur de copie:
L'expression
Dog::new
est appelée référence de méthode . Il crée un objet fonction qui appelle un constructeur surDog
lequel prend un autre chien comme argument.Méthode de clonage [1]:
Obtenir un
ArrayList
résultatOu, si vous devez obtenir un
ArrayList
retour (au cas où vous voudriez le modifier plus tard):Mettre à jour la liste en place
Si vous n'avez pas besoin de conserver le contenu d'origine de la
dogs
liste, vous pouvez plutôt utiliser lareplaceAll
méthode et mettre à jour la liste en place:Tous les exemples supposent
import static java.util.stream.Collectors.*;
.Collectionneur pour
ArrayList
sLe collecteur du dernier exemple peut être transformé en une méthode util. Comme c'est une chose courante à faire, j'aime personnellement que ce soit court et joli. Comme ça:
[1] Remarque sur
CloneNotSupportedException
:Pour que cette solution fonctionne, la
clone
méthode deDog
ne doit pas déclarer qu'elle lanceCloneNotSupportedException
. La raison en est que l'argument tomap
n'est pas autorisé à lever des exceptions vérifiées.Comme ça:
Cela ne devrait cependant pas être un gros problème, car c'est de toute façon la meilleure pratique. ( Effectice Java par exemple donne ce conseil.)
Merci à Gustavo de l'avoir noté.
PS:
Si vous le trouvez plus joli, vous pouvez utiliser la syntaxe de référence de la méthode pour faire exactement la même chose:
la source
List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));
parallel
appel faitclonedDogs.add
être appelé à partir de plusieurs threads en même temps. Les versions qui utilisentcollect
sont thread-safe. C'est l'un des avantages du modèle fonctionnel de la bibliothèque de flux, le même code peut être utilisé pour les flux parallèles.Unhandled exception type CloneNotSupportedException
surd.clone()
. Déclarer l'exception ou l'attraper ne la résout pas.Dog
dans cet exemple) ne prend pas en charge le clonage. Êtes-vous sûr qu'il implémente l'Clonable
interface?Fondamentalement, il existe trois façons sans itérer manuellement,
1 Utilisation du constructeur
2 Utilisation
addAll(Collection<? extends E> c)
3 Utilisation d'une
addAll(int index, Collection<? extends E> c)
méthode avecint
paramètreNB: Le comportement de ces opérations ne sera pas défini si la collection spécifiée est modifiée pendant que l'opération est en cours.
la source
Je pense que la réponse verte actuelle est mauvaise , pourquoi pourriez-vous demander?
La façon dont la sérialisation est également mauvaise imo, vous devrez peut-être ajouter Serializable partout.
Alors, quelle est la solution:
Bibliothèque de clonage en profondeur Java La bibliothèque de clonage est une petite bibliothèque java open source (licence Apache) qui clone en profondeur des objets. Les objets n'ont pas à implémenter l'interface Cloneable. Effectivement, cette bibliothèque peut cloner N'IMPORTE QUEL objet java. Il peut être utilisé, par exemple dans les implémentations de cache, si vous ne voulez pas que l'objet mis en cache soit modifié ou chaque fois que vous voulez créer une copie complète des objets.
Découvrez-le sur https://github.com/kostaskougios/cloning
la source
J'ai trouvé un moyen, vous pouvez utiliser json pour sérialiser / désérialiser la liste. La liste sérialisée ne contient aucune référence à l'objet d'origine lorsqu'elle n'est pas sérialisée.
Utilisation de gson:
Vous pouvez le faire en utilisant également jackson et toute autre bibliothèque json.
la source
J'ai toujours utilisé cette option:
la source
Vous devrez le cloner à la
ArrayList
main (en l'itérant et en copiant chaque élément dans un nouveauArrayList
), car vousclone()
ne le ferez pas pour vous. La raison en est que les objets contenus dans leArrayList
peuvent ne pas s’implémenterClonable
.Edit : ... et c'est exactement ce que fait le code de Varkhan.
la source
Une façon désagréable est de le faire avec réflexion. Quelque chose comme ça a fonctionné pour moi.
la source
original
contient des objets de différentes classes, je pensecloneMethod.invoke
qu'il échouera avec une exception lorsqu'il sera invoqué avec le mauvais type d'objet. Pour cette raison, il peut être préférable de récupérer un clone spécifiqueMethod
pour chaque objet. Ou utilisez la méthode clone surObject
(mais comme celle-ci est protégée, cela peut échouer dans plusieurs cas).Cela copiera en profondeur chaque chien
la source
Les autres affiches sont correctes: vous devez itérer la liste et la copier dans une nouvelle liste.
Cependant ... Si les objets de la liste sont immuables - vous n'avez pas besoin de les cloner. Si votre objet possède un graphique d'objet complexe, il devra également être immuable.
L'autre avantage de l'immuabilité est qu'ils sont également threadsafe.
la source
Voici une solution utilisant un type de modèle générique:
la source
pour vous, les objets remplacent la méthode clone ()
et appelez .clone () pour Vector obj ou ArraiList obj ....
la source
Un moyen facile en utilisant commons-lang-2.3.jar cette bibliothèque de java pour cloner la liste
lien de téléchargement commons-lang-2.3.jar
Comment utiliser
J'espère que celui-ci peut être utile.
:RÉ
la source
Le paquet
import org.apache.commons.lang.SerializationUtils;
Il existe une méthode
SerializationUtils.clone(Object);
Exemple
la source
Je viens de développer une bibliothèque capable de cloner un objet entité et un objet java.util.List. Téléchargez simplement le bocal dans https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U et utilisez la méthode statique cloneListObject (List list). Cette méthode clone non seulement la liste mais également tous les éléments d'entité.
la source
Ce qui suit a fonctionné pour moi ..
dans Dog.java
Ici, la nouvelle liste créée à partir de la méthode createCopy est créée via SerializationUtils.clone (). Ainsi, toute modification apportée à la nouvelle liste n'affectera pas la liste d'origine
la source
Je pense avoir trouvé un moyen très simple de créer une copie complète d'ArrayList. En supposant que vous souhaitez copier un tableau String ArrayList arrayA.
Faites-moi savoir si cela ne fonctionne pas pour vous.
la source