Initialiser une ArrayList Java - Évitez les pièges courants

Noël Besnard .

11 avril 2026

Diagramme des interfaces Java Collections. On y voit `ArrayList` comme implémentation de `List`.

Initialiser une ArrayList en Java paraît simple, mais le bon choix dépend de ce que la liste doit devenir ensuite : mutable, préremplie, issue d’un tableau ou construite à partir d’un flux. Derrière la requête java init arraylist, on cherche souvent une réponse très concrète : quelle syntaxe utiliser, quand réserver une capacité, et surtout quelles options éviter pour ne pas bloquer le code plus tard. Je vais donc aller droit au but avec les méthodes utiles, leurs limites et la manière la plus propre de les utiliser dans un projet moderne.

Les bons réflexes pour initialiser une ArrayList sans piège

  • Pour une liste mutable et vide, new ArrayList<>() reste le choix standard.
  • Si la taille est connue à l’avance, new ArrayList<(taille) limite les reallocations internes.
  • new ArrayList<>(collection) est la meilleure option pour copier une liste existante sans partager son état.
  • Arrays.asList(...) et List.of(...) ne donnent pas une ArrayList mutable prête à recevoir des ajouts.
  • Quand les données viennent d’un stream, Collectors.toCollection(ArrayList::new) est la solution la plus claire si vous voulez une vraie liste modifiable.

Diagramme des interfaces Java Collections. On y voit `ArrayList` comme implémentation de `List`.

Les méthodes d’initialisation à connaître

La première distinction à faire, c’est entre une liste vide mais modifiable et une liste simplement construite à partir de valeurs existantes. En Java, ce n’est pas la même chose, et beaucoup de confusions viennent de là. La syntaxe la plus simple n’est pas toujours la plus adaptée si vous devez ensuite ajouter, supprimer ou transmettre la collection à d’autres couches du code.

Méthode Mutable après création Quand je l’utilise Point d’attention
new ArrayList<>() Oui Pour démarrer une liste vide qui va grandir au fil du code Le constructeur vide crée une capacité initiale de 10, ce qui suffit souvent
new ArrayList<>(10) Oui Quand je connais à peu près le volume à venir Réserve de la place à l’avance, sans changer le contenu
new ArrayList<>(collection) Oui Pour copier une collection existante dans une vraie liste modifiable Crée une nouvelle liste, donc pas de partage d’état avec la source
Arrays.asList(...) Non, taille fixe Pour faire le pont avec un tableau ou construire une base rapide On ne peut pas ajouter ou supprimer d’éléments sans copier ensuite
List.of(...) Non Pour une liste de constantes qui ne doit pas évoluer Disponible à partir de Java 9, refuse les null
Collectors.toCollection(ArrayList::new) Oui Quand la liste provient d’un stream et doit rester modifiable Plus explicite qu’un collecteur générique si l’on veut une vraie ArrayList

Dans la pratique, new ArrayList<>() reste mon point de départ par défaut. Le constructeur vide crée une liste prête à grandir, avec une capacité initiale de dix, ce qui suffit dans la majorité des cas courants. À partir de là, le vrai arbitrage porte surtout sur la mutabilité et sur la provenance des données, ce qui mène directement au choix de la bonne variante.

Quelle variante utiliser selon le besoin réel

Dans le code de production, je pars d’une règle simple : si la liste doit être modifiée, je garde une vraie ArrayList ; si elle doit rester figée, je préfère une liste immuable et je n’essaie pas de la déguiser en ArrayList. Cette distinction évite beaucoup de corrections tardives, surtout quand une méthode commence par renvoyer des données fixes puis devient progressivement un point d’assemblage.

List noms = new ArrayList<>();

J’utilise souvent ce style de déclaration parce qu’il sépare bien l’interface et l’implémentation. Le code parle alors en termes de List, ce qui est plus souple, tout en instanciant une ArrayList quand j’ai besoin de ses performances et de sa mutabilité.

  • Liste à remplir progressivement -> new ArrayList<>()
  • Copie d’une source existante -> new ArrayList<>(source)
  • Valeurs fixes -> List.of(...)
  • Flux -> Collectors.toCollection(ArrayList::new)
  • Taille connue à l’avance -> new ArrayList<>(capacité)

Une fois ce tri mental fait, les pièges deviennent beaucoup plus faciles à repérer, ce qui nous mène justement aux erreurs les plus fréquentes.

Les pièges qui reviennent le plus souvent

Les erreurs sur l’initialisation ne viennent pas d’un manque de syntaxe, mais d’un mauvais modèle mental. Une liste créée avec Arrays.asList(...) n’a pas le même comportement qu’une ArrayList, et une liste issue de List.of(...) n’est pas faite pour évoluer. C’est là que les bugs se glissent, souvent au moment du premier add.

  • Confondre Arrays.asList(...) et ArrayList : cette méthode retourne une liste de taille fixe, pas une collection extensible. Si vous devez ajouter des éléments ensuite, copiez d’abord dans une vraie ArrayList.
  • Utiliser List.of(...) puis essayer d’ajouter : c’est utile pour des constantes, pas pour une construction progressive. En plus, null n’y est pas accepté.
  • Penser que Stream.toList() renvoie une liste modifiable : depuis Java 16, le résultat est non modifiable. Si vous voulez continuer à la faire évoluer, passez par Collectors.toCollection(ArrayList::new).
  • Déclarer des types bruts : ArrayList list = new ArrayList(); fait perdre la sécurité des génériques et ouvre la porte aux erreurs de cast. Je garde toujours le type paramétré.
  • Multiplier les doubles accolades : ce raccourci d’initialisation crée du code moins lisible et ajoute une complexité inutile. Dans un projet maintenu par plusieurs personnes, je préfère une construction explicite avec add ou addAll.
  • Compter sur null sans le décider explicitement : une ArrayList accepte null, mais ce n’est pas une raison pour laisser cette possibilité se propager partout. Mieux vaut définir une règle claire dans le code de l’équipe.

Si vous gardez ces différences en tête, vous évitez la plupart des surprises autour de l’initialisation, et vous rendez le reste du code beaucoup plus prévisible. La suite montre comment remplir la liste proprement, sans sacrifier la lisibilité au profit d’un raccourci trop agressif.

Préremplir une liste proprement

Quand la liste doit démarrer avec quelques éléments, je cherche d’abord la forme la plus lisible, pas la plus « maligne ». Une initialisation claire vaut mieux qu’une expression compacte difficile à relire, surtout si d’autres développeurs doivent ensuite ajouter des règles métier autour.

List technologies = new ArrayList<>(List.of("Java", "Kotlin", "Scala"));
technologies.add("Groovy");

Cette version est utile parce que List.of(...) sert de source propre, puis new ArrayList<>(...) redonne une structure modifiable. Je m’en sers souvent quand je pars d’un socle fixe mais que je sais déjà que la liste devra évoluer ensuite.

ArrayList tags = new ArrayList<>();
Collections.addAll(tags, "ai", "cloud", "security");
Pour des valeurs connues à l’avance, Collections.addAll(...) reste simple et lisible. Si les données arrivent d’un stream, je préfère Collectors.toCollection(ArrayList::new) à Stream.toList(), parce que la première option donne directement une ArrayList mutable alors que la seconde renvoie une liste non modifiable depuis Java 16.

Ce choix devient encore plus intéressant quand vous travaillez sur des traitements de données ou des pipelines où la collection sert d’étape intermédiaire. Et à partir de là, la vraie question n’est plus seulement “comment la créer”, mais aussi “faut-il réserver de la place à l’avance ?”.

Capacité, performances et lisibilité au quotidien

Le sujet des performances est souvent surjoué, mais il n’est pas inutile. Si vous savez qu’une liste va contenir plusieurs centaines ou milliers d’éléments, je réserve la capacité au départ avec new ArrayList<>(tailleEstimée) ou ensureCapacity(...) pour limiter les réallocations internes. À l’inverse, si vous ne connaissez pas le volume, le constructeur vide reste le choix le plus raisonnable.

  • Petites listes imprévisibles : je garde new ArrayList<>().
  • Import massif ou boucle connue : je passe par une capacité initiale ou ensureCapacity(...).
  • Liste stabilisée et très volumineuse : je n’utilise trimToSize() que si l’économie mémoire compte vraiment.

Je n’utilise trimToSize() que dans des cas bien ciblés, parce que le gain mémoire ne justifie pas toujours le coût et la complexité mentale ajoutée. Si vous n’avez pas de signal concret, restez simple : la clarté du code rapporte plus qu’une optimisation prématurée. C’est précisément ce genre de discipline qui facilite ensuite le choix final.

La règle simple que j’applique avant de créer une ArrayList

Avant de trancher, je me pose une seule question : cette liste doit-elle évoluer ? Si la réponse est oui, j’utilise List avec new ArrayList<>() ou une copie mutable d’une source existante. Si la réponse est non, je garde une structure immuable et je n’essaie pas de la transformer artificiellement en ArrayList.

  • mutable -> new ArrayList<>()
  • source existante -> new ArrayList<>(source)
  • valeurs fixes -> List.of(...)
  • stream -> Collectors.toCollection(ArrayList::new)

Cette approche réduit les surprises, garde le code lisible et rend l’intention visible dès la déclaration. C’est ce que je privilégie presque toujours dans un projet Java moderne, parce qu’une bonne initialisation ne se voit pas seulement à l’exécution, elle se comprend immédiatement à la lecture.

Questions fréquentes

`new ArrayList<>()` crée une liste vide et mutable, prête à être modifiée (ajout/suppression d'éléments). `Arrays.asList()` crée une liste de taille fixe à partir d'un tableau ou d'éléments donnés. Cette dernière n'est pas modifiable en termes de taille, tenter d'ajouter ou de supprimer des éléments entraînera une erreur.
Il est recommandé de spécifier la capacité initiale (`new ArrayList<>(tailleEstimée)`) lorsque vous avez une bonne estimation du nombre d'éléments que la liste contiendra. Cela permet d'éviter les réallocations internes coûteuses et d'améliorer les performances, surtout pour les listes de grande taille. Pour les petites listes ou les tailles inconnues, le constructeur par défaut est suffisant.
Non, `List.of()` (disponible depuis Java 9) crée une liste immuable. Cela signifie que vous ne pouvez ni ajouter, ni supprimer, ni modifier les éléments après sa création. C'est idéal pour des collections de constantes, mais si vous avez besoin d'une ArrayList modifiable, vous devrez la copier dans une nouvelle `ArrayList` comme ceci : `new ArrayList<>(List.of("element1", "element2"))`.
Pour initialiser une ArrayList à partir d'un Stream tout en garantissant qu'elle reste modifiable, utilisez `Collectors.toCollection(ArrayList::new)`. La méthode `Stream.toList()` (introduite en Java 16) renvoie une liste non modifiable par défaut. L'utilisation de `toCollection` assure que vous obtenez une véritable `ArrayList` sur laquelle vous pourrez effectuer des opérations d'ajout et de suppression.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

java init arraylist initialiser arraylist java java arraylist constructeur arraylist mutable java
Autor Noël Besnard
Noël Besnard
Je suis Noël Besnard, un analyste de l'industrie passionné par les domaines de la technologie, notamment le web, l'intelligence artificielle, les réseaux et la sécurité. Avec plus de dix ans d'expérience dans l'analyse des tendances du marché technologique, j'ai acquis une expertise approfondie qui me permet d'explorer les innovations et les défis auxquels notre monde numérique est confronté. Mon approche consiste à simplifier des données complexes et à fournir une analyse objective, ce qui me permet de rendre les sujets techniques accessibles à tous. Je m'engage à offrir des informations précises et à jour, en vérifiant rigoureusement les faits pour garantir la fiabilité de chaque article que je publie. Mon objectif est d'aider les lecteurs à naviguer dans cet univers en constante évolution, en leur fournissant les outils nécessaires pour comprendre les enjeux technologiques contemporains.

Commentaires (0)

Ajouter un commentaire