J'ai un ArrayList
et je veux le copier exactement. J'utilise des classes d'utilité lorsque cela est possible en supposant que quelqu'un a passé du temps à le corriger. Alors naturellement, je me retrouve avec la Collections
classe qui contient une méthode de copie.
Supposons que j'ai ce qui suit:
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b,a);
Cela échoue parce qu'il pense que ce b
n'est pas assez grand pour tenir a
. Oui, je sais qu'il b
a la taille 0, mais il devrait être assez grand maintenant, n'est-ce pas? Si je dois remplir en b
premier, cela Collections.copy()
devient une fonction complètement inutile dans mon esprit. Donc, à part la programmation d'une fonction de copie (ce que je vais faire maintenant), y a-t-il un moyen approprié de le faire?
java
list
collections
copy
Plancher Jasper
la source
la source
Réponses:
Appel
crée une copie superficielle de l'
a
intérieurb
. Tous les éléments existeront à l'intérieurb
dans le même ordre exact dans lequel ils étaienta
(en supposant qu'il y avait un ordre).De même, appeler
crée également une copie superficielle de l'
a
intérieurb
. Si le premier paramètre,,b
n'a pas assez de capacité (pas de taille) pour contenir tousa
les éléments de, alors il lancera unIndexOutOfBoundsException
. On s'attend à ce qu'aucune allocation ne soit requiseCollections.copy
pour fonctionner, et le cas échéant, il lève cette exception. C'est une optimisation d'exiger que la collection copiée soit préallouée (b
), mais je ne pense généralement pas que la fonctionnalité en vaille la peine en raison des vérifications requises étant donné les alternatives basées sur le constructeur comme celle montrée ci-dessus qui n'ont pas d'effets secondaires étranges.Pour créer une copie complète, le
List
, via l'un ou l'autre mécanisme, devrait avoir une connaissance approfondie du type sous-jacent. Dans le cas deString
s, qui sont immuables en Java (et .NET d'ailleurs), vous n'avez même pas besoin d'une copie complète. Dans le cas deMySpecialObject
, vous devez savoir comment en faire une copie complète et ce n'est pas une opération générique.Remarque: La réponse acceptée à l'origine était le meilleur résultat pour
Collections.copy
Google, et elle était tout à fait erronée comme indiqué dans les commentaires.la source
b
a une capacité de 3, mais une taille de 0. Le fait d'ArrayList
avoir une sorte de capacité tampon est un détail d'implémentation - il ne fait pas partie de l'List
interface, doncCollections.copy(List, List)
ne l'utilise pas. Ce serait moche pour cela à des cas spéciauxArrayList
.Comme MrWiggles l'a indiqué, utiliser le constructeur ArrayList qui prend une collection est le moyen de le faire dans l'exemple fourni.
Pour des scénarios plus compliqués (qui peuvent inclure votre vrai code), vous pouvez trouver les collections de Guava utiles.
la source
Faites simplement:
ArrayList a un constructeur qui acceptera une autre Collection pour copier les éléments depuis
la source
String
objets sont immuables.La réponse de Stephen Katulka (réponse acceptée) est fausse (la deuxième partie). Il explique que cela
Collections.copy(b, a);
fait une copie profonde, ce qui n'est pas le cas. Les deux,new ArrayList(a);
etCollections.copy(b, a);
ne font qu'une copie superficielle. La différence est que le constructeur alloue une nouvelle mémoire, etcopy(...)
non, ce qui le rend approprié dans les cas où vous pouvez réutiliser des tableaux, car il y a un avantage en termes de performances.L'API standard Java tente de décourager l'utilisation de copies approfondies, car il serait mauvais que de nouveaux codeurs l'utilisent régulièrement, ce qui peut également être l'une des raisons pour lesquelles ce
clone()
n'est pas public par défaut.Le code source de
Collections.copy(...)
peut être consulté sur la ligne 552 à l' adresse : http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/Collections-Jar-Zip-Logging-regex/java/util/ Collections.java.htmSi vous avez besoin d'une copie complète, vous devez parcourir les éléments manuellement, en utilisant une boucle for et clone () sur chaque objet.
la source
la manière la plus simple de copier une liste est de la passer au constructeur de la nouvelle liste:
b
sera une copie superficielle dea
En regardant la source de
Collections.copy(List,List)
(je ne l'avais jamais vu auparavant), il semble que ce soit pour faire face aux éléments index par index. utiliserList.set(int,E)
ainsi l'élément 0 écrasera l'élément 0 dans la liste cible, etc. Pas particulièrement clair d'après les javadocs que je devrais admettre.la source
ne définit pas la taille. Il définit la capacité initiale (c'est-à-dire le nombre d'éléments dans lesquels il peut s'intégrer avant de devoir redimensionner). Une façon plus simple de copier dans ce cas est:
la source
Comme le mentionne hoijui. La réponse sélectionnée de Stephen Katulka contient un commentaire sur Collections.copy qui est incorrect. L'auteur l'a probablement accepté parce que la première ligne de code faisait la copie qu'il voulait. L'appel supplémentaire à Collections.copy ne fait que copier à nouveau. (Résultant en la copie se produisant deux fois).
Voici le code pour le prouver.
la source
La plupart des réponses ici ne réalisent pas le problème, l'utilisateur veut avoir une COPIE des éléments de la première liste à la deuxième liste, les éléments de la liste de destination sont de nouveaux objets et non une référence aux éléments de la liste d'origine. (signifie que changer un élément de la deuxième liste ne devrait pas changer les valeurs de l'élément correspondant de la liste source.) Pour les objets mutables, nous ne pouvons pas utiliser le constructeur ArrayList (Collection) car il fera simplement référence à l'élément de liste d'origine et ne copiera pas. Vous devez avoir un cloneur de liste pour chaque objet lors de la copie.
la source
Pourquoi n'utilisez-vous pas simplement la
addAll
méthode:même si vous avez des éléments existants dans b ou que vous souhaitez suspendre certains éléments après lui, tels que:
la source
Si vous souhaitez copier une ArrayList, copiez-la en utilisant:
la source
Les chaînes peuvent être copiées en profondeur avec
parce qu'ils sont immuables. Tous les autres objets non -> vous devez itérer et faire une copie par vous-même.
la source
b
pointe vers le mêmeString
objet correspondant dansa
. Cependant, ce n'est pas important car, comme vous le faites remarquer, lesString
objets sont immuables.la source
Tous les autres objets non -> vous devez itérer et faire une copie par vous-même.
Pour éviter cette implémentation Cloneable.
....
la source
La sortie suivante illustre les résultats de l'utilisation du constructeur de copie et de Collections.copy ():
La source du programme complet est ici: Copie de la liste Java . Mais la sortie est suffisante pour voir comment se comporte java.util.Collections.copy ().
la source
Et si vous utilisez google guava, la solution en une seule ligne serait
Cela crée une instance de liste de tableaux mutable.
la source
Avec Java 8 étant de type null-safe, vous pouvez utiliser le code suivant.
Ou en utilisant un collectionneur
la source
La copie n'est pas inutile si vous imaginez le cas d'utilisation pour copier certaines valeurs dans une collection existante. Par exemple, vous souhaitez écraser les éléments existants au lieu de les insérer.
Un exemple: a = [1,2,3,4,5] b = [2,2,2,2,3,3,3,3,3,4,4,4,] a.copy (b) = [1,2,3,4,5,3,3,3,3,4,4,4]
Cependant, je m'attendrais à une méthode de copie qui prendrait des paramètres supplémentaires pour l'index de début de la collection source et cible, ainsi qu'un paramètre pour le nombre.
Voir Java BUG 6350752
la source
Pour comprendre pourquoi Collections.copy () lève une exception IndexOutOfBoundsException bien que vous ayez suffisamment étendu le tableau de sauvegarde de la liste de destination (via l'appel size () sur la sourceList), consultez la réponse d'Abhay Yadav dans cette question connexe: Comment faire copier une java.util.List dans une autre java.util.List
la source