Conversion d’une collection en ArrayList en Java

Conversion d'une collection en ArrayList en Java

1. Vue d'ensemble

La conversion de collections Java d'un type à un autre est une tâche de programmation courante. Dans ce didacticiel, nous allons convertir tout type deCollection enArrayList.

Tout au long du didacticiel, nous supposerons que nous avons déjà une collection d'objetsFoo. À partir de là, nous allons créer unArrayList uivant différentes approches.

2. Définir notre exemple

Mais avant de continuer, modélisons nos entrées et sorties.

Notre source peut être n'importe quel type de collection, nous allons donc la déclarer à l'aide de l'interfaceCollection:

Collection srcCollection;

Nous devons produire unArrayList avec le même type d'élément:

ArrayList newList;

3. Utilisation du constructeur ArrayList

Le moyen le plus simple de copier une collection dans une nouvelle collection consiste à utiliser son constructeur.

Dans nosguide to ArrayList précédents, nous avons appris que le constructeurArrayList peut accepter un paramètre de collection:

ArrayList newList = new ArrayList<>(srcCollection);
  • Le nouveauArrayList contient une copie superficielle des éléments Foo dans la collection source.

  • La commande est la même que celle de la collection source.

La simplicité du constructeur en fait une excellente option dans la plupart des scénarios.

4. Utilisation de l'API Streams

Maintenant,let’s take advantage of the Streams API to create an ArrayList from an existing Collection: _ _

ArrayList newList = srcCollection.stream().collect(toCollection(ArrayList::new));

Dans cet extrait:

  • Nous prenons le flux de la collection source et appliquons l'opérateurcollect() pour créer unList

  • Nous spécifionsArrayList::new pour obtenir le type de liste que nous voulons

  • Ce code produira également une copie superficielle.

Si nous n'étions pas préoccupés par le type exact deList, nous pourrions simplifier:

List newList = srcCollection.stream().collect(toList());

Notez quetoCollection() ettoList() sont importés statiquement deCollectors. Pour en savoir plus, veuillez consulter nosguide on Java 8’s Collectors.

5. Copie Profonde

Avant nous avons mentionné "copies peu profondes". Par cela, nous entendons lesthe elements in the new list are exactly the same Foo instances qui existent toujours dans la collection source. Par conséquent, nous avons copié lesFoos dans lesnewList par référence.

Si nous modifions le contenu d'une instance deFoo dans l'une ou l'autre des collections,modification will be reflected in both collections. Par conséquent, si nous voulons modifier les éléments de l'une ou l'autre des collectionswithout en modifiant l'autre, nous devons effectuer une «copie complète».

Pour copier en profondeur unFoo, nouscreate a completely new Foo instance for each element. Par conséquent, tous les champsFoo doivent être copiés dans les nouvelles instances.

Définissons notre classeFoo afin qu'elle sache comment se copier en profondeur:

public class Foo {

    private int id;
    private String name;
    private Foo parent;

    public Foo(int id, String name, Foo parent) {
        this.id = id;
        this.name = name;
        this.parent = parent;
    }

    public Foo deepCopy() {
        return new Foo(
          this.id, this.name, this.parent != null ? this.parent.deepCopy() : null);
    }
}

Ici, nous pouvons voir que les champsid etname sontint etString. Ces types de données sont copiés par valeur. Par conséquent, nous pouvons simplement assigner les deux.

Le champparent est un autreFoo, qui est une classe. SiFoo got muté, tout code qui partage cette référence serait affecté par ces changements. We have to deep copy the parent field.

Nous pouvons maintenant revenir à notre conversionArrayList. We just need the map operator to insert the deep copy dans le flux:

ArrayList newList = srcCollection.stream()
  .map(foo -> foo.deepCopy())
  .collect(toCollection(ArrayList::new));

Nous pouvons modifier le contenu de l'une ou l'autre des collections sans affecter l'autre.

Une copie en profondeur peut être un processus long en fonction du nombre d'éléments et de la profondeur des données. L'utilisation d'un flux parallèle ici peut améliorer les performances si nécessaire.

6. Contrôle de l'ordre de la liste

Par défaut, notre flux livrera les éléments à nosArrayList dans le même ordre qu'ils sont rencontrés dans la collection source.

Si nous voulons changer cet ordrewe could apply the sorted() operator to the stream. Pour trier nos objetsFoo par nom:

ArrayList newList = srcCollection.stream()
  .sorted(Comparator.comparing(Foo::getName))
  .collect(toCollection(ArrayList::new));

Nous pouvons trouver plus de détails sur l'ordre des flux dans ceearlier tutorial.

7. Conclusion

Le constructeurArrayList est un moyen efficace d'obtenir le contenu d'unCollection dans un nouveauArrayList.

Toutefois, si nous devons modifier la liste résultante, l’API Streams constitue un moyen puissant de modifier le processus.

Le code utilisé dans cet article se trouve dans son intégralitéover on GitHub.