web-dev-qa-db-fra.com

Jeux de copie Java

Est-il possible de copier un TreeSet? C'est, est-il possible d'aller

Set <Item> itemList;
Set <Item> tempList;

tempList = itemList;

ou devez-vous parcourir physiquement les ensembles et les copier un par un?

77
SNpn

Une autre façon de faire est d'utiliser le constructeur de la copie :

Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>(oldSet);

Ou créez un ensemble vide et ajoutez les éléments:

Collection<E> oldSet = ...
TreeSet<E> newSet = new TreeSet<E>();
newSet.addAll(oldSet);

Contrairement à clone, ils vous permettent d'utiliser une classe de jeu différente, un comparateur différent ou même de renseigner un type de collection (non défini).


Notez que le résultat de la copie d'un Set est un nouveau Set contenant des références aux objets qui sont des éléments si l'original Set. Les objets élément eux-mêmes ne sont ni copiés ni copiés. Ceci est conforme à la manière dont les API Java Collection sont conçues pour fonctionner: elles ne copient pas les objets élément.

145
Stephen C

Avec Java 8, vous pouvez utiliser stream et collect pour copier les éléments:

Set<Item> newSet = oldSet.stream().collect(Collectors.toSet());

Ou vous pouvez collecter dans un ImmutableSet (si vous savez que l'ensemble ne devrait pas changer):

Set<Item> newSet = oldSet.stream().collect(ImmutableSet.toImmutableSet());
6
Yosi Dahari

Le constructeur de copie donné par @Stephen C est la voie à suivre quand vous avez créé un Set (ou quand vous savez d'où il vient). Quand cela vient d'un Map.entrySet() , cela dépendra de l'implémentation Map que vous utilisez:

findbugs dit

La méthode entrySet () est autorisée à renvoyer une vue de la mappe sous-jacente dans laquelle un seul objet Entry est réutilisé et renvoyé lors de l'itération. À partir de Java 1.6, IdentityHashMap et EnumMap l'ont fait. Lors d'une itération dans une telle carte, la valeur de l'entrée n'est valide que jusqu'à ce que vous passiez à l'itération suivante. Si, par exemple, vous essayez de passer un tel entrySet à une méthode addAll, les choses iront très mal.

Comme addAll() est appelé par le constructeur de la copie, vous pourriez vous retrouver avec un ensemble d'une seule entrée: la dernière.

Cependant, toutes les implémentations Map ne le font pas. Par conséquent, si vous savez que votre implémentation est sûre à cet égard, le constructeur de copie est définitivement la voie à suivre. Sinon, vous devrez créer vous-même de nouveaux objets Entry:

Set<K,V> copy = new HashSet<K,V>(map.size());
for (Entry<K,V> e : map.entrySet())
    copy.add(new Java.util.AbstractMap.SimpleEntry<K,V>(e));

Edit: Contrairement aux tests que j’ai effectués sur Java 7 et Java 6u45 (grâce à Stephen C), le commentaire de findbugs ne semble plus approprié. C'était peut-être le cas sur les versions précédentes de Java 6 (avant u45), mais je n'ai pas de test à tester.

3
Matthieu

À partir de Java 10 :

Set<E> oldSet = Set.of();
Set<E> newSet = Set.copyOf(oldSet);

Set.copyOf() retourne un Set non modifiable contenant les éléments du Collection donné.

Le Collection donné ne doit pas être null, et il ne doit contenir aucun élément null.

3
Oleksandr Pyrohov