Un tableau Java (int[]) a une taille fixe : impossible d’y ajouter un élément une fois créé. Dans un vrai programme (panier, liste d’élèves, lignes d’un fichier), on ne connaît pas la taille à l’avance. Le framework Collections (java.util) répond à ce besoin, et la collection la plus utilisée est la liste.
Déclarer une liste
import java.util.ArrayList;
import java.util.List;
List<String> courses = new ArrayList<>(); // interface à gauche, implémentation à droite
courses.add("pain"); // ajoute à la fin
courses.add("lait");
courses.add(0, "café"); // insère à l'index 0
System.out.println(courses); // [café, pain, lait]
System.out.println(courses.get(1)); // pain
courses.set(1, "baguette"); // remplace l'élément d'index 1
System.out.println(courses.size()); // 3
System.out.println(courses.contains("lait")); // true
Depuis Java 21, les listes sont des collections séquencées : elles offrent des raccourcis pour les extrémités, plus lisibles que get(0) ou get(liste.size() - 1) :
courses.getFirst(); // "café" (NoSuchElementException si la liste est vide)
courses.getLast(); // "lait"
courses.addFirst("thé"); // équivaut à add(0, "thé")
courses.reversed(); // vue en ordre inverse : [lait, baguette, café, thé]
Le <String> est un type générique : le compilateur refuse d’ajouter autre chose qu’une String, et get renvoie directement une String, sans conversion. L’opérateur diamant <> évite de répéter le type.
Les génériques n’acceptent que des objets : on écrit List<Integer>, pas List<int>. Java convertit automatiquement int en Integer (autoboxing).
Pourquoi déclarer avec
Listplutôt qu’ArrayList? Pour pouvoir changer d’implémentation (par exempleLinkedList) sans toucher au reste du code. C’est le principe « programmer vers une interface ».
Le piège de remove
List<Integer> notes = new ArrayList<>(List.of(10, 20, 30));
notes.remove(1); // supprime l'élément d'INDEX 1 -> [10, 30]
notes.remove(Integer.valueOf(30)); // supprime la VALEUR 30 -> [10]
Listes immuables
List.of("a", "b") crée une liste non modifiable : add ou remove lèvent une UnsupportedOperationException. C’est idéal pour des constantes ou pour renvoyer des données qu’on ne veut pas voir modifiées. Pour obtenir une copie modifiable : new ArrayList<>(List.of(...)). Pour une copie immuable d’une liste existante : List.copyOf(liste).
Parcourir et supprimer en toute sécurité
for (String article : courses) {
System.out.println("- " + article);
}
// ERREUR classique : supprimer pendant un for-each
// for (String a : courses) { if (a.startsWith("b")) courses.remove(a); }
// -> ConcurrentModificationException
courses.removeIf(a -> a.startsWith("b")); // la bonne façon
removeIf prend une condition (une lambda, que nous approfondirons dans la leçon 3) et supprime tous les éléments qui la vérifient.
À retenir
ArrayListest la liste par défaut : accès par index rapide, ajout en fin rapide.- Déclarez avec l’interface
List<T>. List.of= immuable ;new ArrayList<>(...)= modifiable.- Pas de suppression dans un for-each : utilisez
removeIf.
Exercices
Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.
Nettoyer une liste de mesures
Lisez une ligne de nombres entiers séparés par des espaces. Stockez-les dans une
List<Integer>, supprimez les valeurs négatives avecremoveIf, puis affichez :[3, 4, 9] taille=3 somme=16(la liste avec
System.out.println(liste), puis sa taille, puis la somme). Une ligne vide donne une liste vide.import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String ligne = sc.hasNextLine() ? sc.nextLine().trim() : ""; List<Integer> mesures = new ArrayList<>(); // TODO : remplir la liste, supprimer les négatifs, afficher } }Liste de courses pilotée par commandes
Chaque ligne de l’entrée est une commande :
ADD x: ajoutexà la fin ;INSERT i x: insèrexà l’indexi;REMOVE x: supprime la première occurrence dex, ou afficheabsent: xsi elle n’existe pas.
À la fin, affichez la liste numérotée à partir de 1 (
1. pain). Si la liste est vide, affichezliste vide.import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); List<String> courses = new ArrayList<>(); while (sc.hasNextLine()) { String[] p = sc.nextLine().trim().split(" "); // TODO : traiter ADD, INSERT et REMOVE } // TODO : afficher la liste numérotée } }Liste immuable
Que se passe-t-il à l’exécution de
List<String> l = List.of("a"); l.add("b");?- La liste contient [a, b]
- Une UnsupportedOperationException est levée
- Le code ne compile pas
- add renvoie false sans rien changer
Quiz de fin de leçon
Quelle déclaration est recommandée ?
- ArrayList<String> l = new ArrayList<String>();
- List<String> l = new ArrayList<>();
- List l = new ArrayList();
Sur une List
valant [5, 6, 7], que donne remove(1) ? - [6, 7]
- [5, 7]
- [5, 6, 7]
Comment supprimer tous les éléments vides d’une List
modifiable ? - Dans un for-each avec liste.remove(s)
- liste.removeIf(String::isEmpty)
- liste.delete("")
La suite du cours
- Ensembles et dictionnaires : Set et Map18 min
- Lambdas, Comparator et premiers streams18 min
- Collectors, regroupements et Optional18 min
- Gérer les erreurs avec les exceptions20 min