HOWTO · Java

Copier ArrayList en Java

Cet article présente différentes méthodes pour copier une ArrayList dans une autre liste en Java.

Sur cette page

Pour copier une ArrayList dans une liste distincte en Java, utilisez le constructeur de copie pour créer une nouvelle liste initialisée à partir de la source. Vous pouvez également utiliser addAll(), un flux ou clone(). Ces méthodes copient la structure de la liste, pas les objets qu’elle contient : si un élément est mutable, les deux listes font toujours référence au même objet. Les exemples utilisent les mêmes noms afin de comparer la façon dont chaque méthode crée ou remplit la liste de destination.

Choisir une méthode de copie pour une ArrayList

Choisissez new ArrayList<>(source) pour créer directement une nouvelle liste à partir d’une collection existante. Utilisez destination.addAll(source) si vous avez déjà une liste de destination et souhaitez y ajouter les éléments de la source ; videz-la d’abord uniquement si vous voulez remplacer son contenu. Un flux est utile lorsqu’il s’intègre déjà à une chaîne de transformations, mais Collectors.toList() garantit une List, pas une ArrayList en particulier. Transmettez son résultat au constructeur de copie si votre code exige ce type concret. clone() est une autre option de copie superficielle, mais son type de retour Object impose un cast.

Une copie superficielle possède une structure de liste indépendante : ajouter ou retirer un élément d’une liste ne modifie ni la taille ni l’ordre de l’autre. En revanche, les références aux éléments sont partagées. Par exemple, si vous copiez une liste d’objets StringBuilder mutables, puis appelez setLength(0) sur un objet obtenu depuis la copie, la liste source reflète elle aussi cette modification. Pour copier les éléments mutables indépendamment, créez également de nouveaux objets pour ces éléments ; aucune des quatre méthodes ci-dessous ne réalise cette copie plus profonde. Les chaînes des exemples sont immuables : elles facilitent la comparaison des opérations sur les listes sans laisser entendre que la copie reproduit aussi les modifications des éléments.

Copier une ArrayList avec son constructeur de copie

Le constructeur qui accepte une collection initialise une nouvelle ArrayList avec les éléments de la source, dans leur ordre d’itération. C’est le choix concis par défaut lorsque vous avez besoin d’une autre liste sans transformer les éléments. La source reste une liste distincte, mais les références aux éventuels éléments mutables sont partagées.

Exécutez cet exemple :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

import java.util.ArrayList;

public class CopyArrayList {
  public static void main(String[] args) {
    ArrayList<String> names1 = new ArrayList<>();
    names1.add("Alan");
    names1.add("Alex");
    names1.add("Bob");
    names1.add("Bryan");
    names1.add("Cathy");
    names1.add("Drake");

    ArrayList<String> names2 = new ArrayList<>(names1);
    names2.forEach(System.out::println);
  }
}

Copier des éléments avec addAll()

addAll() ajoute chaque élément de la collection fournie à la fin de la liste de destination et indique si celle-ci a été modifiée. La méthode ne remplace pas le contenu existant. Pour obtenir une nouvelle copie, commencez par une liste de destination vide, comme ci-dessous. Si la destination contient déjà des éléments, ceux-ci restent au début et les éléments de la source viennent ensuite. Cette opération produit elle aussi une copie superficielle : les listes sont distinctes, mais les éléments mutables restent partagés.

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

import java.util.ArrayList;

public class CopyArrayList {
  public static void main(String[] args) {
    ArrayList<String> names1 = new ArrayList<>();
    names1.add("Alan");
    names1.add("Alex");
    names1.add("Bob");
    names1.add("Bryan");
    names1.add("Cathy");
    names1.add("Drake");

    ArrayList<String> names2 = new ArrayList<>();
    names2.addAll(names1);
    names2.forEach(System.out::println);
  }
}

Copier une ArrayList avec un flux

Un flux peut rassembler les éléments de la source dans une liste, mais Collectors.toList() ne garantit pas une implémentation particulière. Ne convertissez pas directement ce résultat en ArrayList : le contrat garantit seulement une List, donc ce cast n’est pas sûr. En construisant une ArrayList à partir de la liste obtenue, vous demandez explicitement le type concret voulu. Cette méthode copie elle aussi les références, et non les éléments mutables.

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

import java.util.ArrayList;
import java.util.stream.Collectors;

public class CopyArrayList {
  public static void main(String[] args) {
    ArrayList<String> names1 = new ArrayList<>();
    names1.add("Alan");
    names1.add("Alex");
    names1.add("Bob");
    names1.add("Bryan");
    names1.add("Cathy");
    names1.add("Drake");

    ArrayList<String> names2 = new ArrayList<>(
        names1.stream().collect(Collectors.toList()));
    names2.forEach(System.out::println);
  }
}

Copier une ArrayList avec clone()

ArrayList.clone() crée une copie superficielle et son type de retour déclaré est Object. Pour utiliser le résultat comme une ArrayList, convertissez-le avec un cast ; comme le type générique des éléments est effacé, ce cast n’est pas vérifié et produit normalement un avertissement du compilateur. Toutefois, l’annotation @SuppressWarnings("unchecked") placée sur la déclaration de cet exemple supprime cet avertissement. Limitez ce cast aux listes dont vous savez qu’elles contiennent le type d’élément attendu. Préférez le constructeur de copie si vous voulez éviter ce cast et cet avertissement.

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

import java.util.ArrayList;

public class CopyArrayList {
  public static void main(String[] args) {
    ArrayList<String> names1 = new ArrayList<>();
    names1.add("Alan");
    names1.add("Alex");
    names1.add("Bob");
    names1.add("Bryan");
    names1.add("Cathy");
    names1.add("Drake");

    @SuppressWarnings("unchecked")
    ArrayList<String> names2 = (ArrayList<String>) names1.clone();
    names2.forEach(System.out::println);
  }
}