J'ai un List<SomeBean>
qui est rempli à partir d'un service Web. Je veux copier/cloner le contenu de cette liste dans une liste vide du même type. Une recherche sur Google pour copier une liste m'a suggéré d'utiliser la méthode Collections.copy()
. Dans tous les exemples que j'ai vus, la liste de destinataires devait contenir le nombre exact d'éléments pour la copie.
Comme la liste que j’utilise est alimentée par un service Web et qu’elle contient des centaines d’objets, je ne peux pas utiliser la technique ci-dessus. Ou je l'utilise mal ?? !! Quoi qu'il en soit, pour que cela fonctionne, j'ai essayé de faire quelque chose comme ça, mais j'ai quand même un IndexOutOfBoundsException
.
List<SomeBean> wsList = app.allInOne(template);
List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList.size());
Collections.copy(wsListCopy,wsList);
System.out.println(wsListCopy.size());
J'ai essayé d'utiliser la wsListCopy=wsList.subList(0, wsList.size())
mais j'ai reçu une ConcurrentAccessException
plus tard dans le code. Hit et procès. :)
Quoi qu'il en soit, ma question est simple, comment copier tout le contenu de ma liste dans une autre liste? Pas par itération, bien sûr.
Il suffit d'utiliser ceci:
List<SomeBean> newList = new ArrayList<SomeBean>(otherList);
Remarque: vous ne pouvez toujours pas utiliser les threads si vous modifiez otherList
à partir d'un autre thread. Dans ce cas, vous souhaiterez peut-être que otherList
(et même newList
) devienne CopyOnWriteArrayList
, par exemple, ou utiliserez une primitive de verrouillage, telle que ReentrantReadWriteLock pour sérialiser les accès en lecture/écriture à toutes les listes auxquelles on accède simultanément.
Voici une façon très agréable de procéder avec Java 8:
List<String> list2 = list1.stream().collect(Collectors.toList());
Bien entendu, l’avantage ici est que vous pouvez filtrer et passer à la copie d’une partie seulement de la liste.
par exemple.
//don't copy the first element
List<String> list2 = list1.stream().skip(1).collect(Collectors.toList());
originalArrayList.addAll(copyArrayofList);
N'oubliez pas que lorsque vous utilisez la méthode addAll () pour la copie, le contenu des deux listes de tableaux (originalArrayList et copyArrayofList) faisant référence aux mêmes objets est ajouté à la liste. Par conséquent, si vous en modifiez une, copyArrayofList reflétera également le même changement.
Si vous ne voulez pas d'effet secondaire, vous devez copier chacun des éléments de l'originalArrayList dans copyArrayofList, comme si vous utilisiez une boucle for ou while.
J'ai essayé de faire quelque chose comme ça, mais j'ai toujours une exception IndexOutOfBoundsException.
J'ai eu une exception concurrente
Cela signifie que vous modifiez la liste pendant que vous essayez de la copier, probablement dans un autre thread. Pour résoudre ce problème, vous devez soit
utilisez une collection conçue pour un accès simultané.
verrouillez la collection de manière appropriée afin que vous puissiez la parcourir (ou vous permettre d'appeler une méthode qui le fait pour vous)
rechercher un lieu pour éviter de devoir copier la liste originale.
En Java 10:
List<T> newList = List.copyOf(oldList);
List.copyOf()
retourne une List
non modifiable contenant les éléments de la Collection
donnée.
La variable Collection
donnée ne doit pas être null
et ne doit contenir aucun élément null
.
Il existe une autre méthode avec Java 8 de manière null-safe.
List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
.map(List::stream)
.orElseGet(Stream::empty)
.collect(Collectors.toList());
Si vous voulez ignorer un élément.
List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
.map(List::stream)
.orElseGet(Stream::empty)
.skip(1)
.collect(Collectors.toList());
J'avais le même problème ConcurrentAccessException et ma résolution était de:
List<SomeBean> tempList = new ArrayList<>();
for (CartItem item : prodList) {
tempList.add(item);
}
prodList.clear();
prodList = new ArrayList<>(tempList);
Donc, cela ne fonctionne qu'une opération à la fois et évite l'Exception ...
J'ai essayé quelque chose de similaire et j'ai pu reproduire le problème (IndexOutOfBoundsException). Ci-dessous sont mes conclusions:
1) L’implémentation de Collections.copy (destList, sourceList) vérifie d’abord la taille de la liste de destination en appelant la méthode size (). Comme l’appel à la méthode size () retournera toujours le nombre d’éléments de la liste (0 dans ce cas), le constructeur ArrayList (capacity) n’assure que la capacité initiale du tableau de sauvegarde, ce qui n’a aucune relation avec le taille de la liste. Par conséquent, nous obtenons toujours IndexOutOfBoundsException.
2) Un moyen relativement simple consiste à utiliser le constructeur qui prend une collection comme argument:
List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);
Vous pouvez utiliser addAll ().
par exemple: wsListCopy.addAll(wsList);
re: indexOutOfBoundsException
, vos arguments de sous-liste sont le problème; vous devez terminer la sous-liste à la taille-1. Étant basé sur zéro, le dernier élément d'une liste est toujours la taille-1, il n'y a pas d'élément dans la position de la taille, d'où l'erreur.
Je ne vois pas de réponse correcte. Si vous voulez une copie en profondeur, vous devez itérer et copier l'objet manuellement (vous pouvez utiliser un constructeur de copie).