Essayer de coder ← Retour aux sujets

ArrayList : la liste qui grandit

ArrayList<T>

Une ArrayList est un tableau redimensionnable : elle contient des objets d'un type précisé entre chevrons (<String>, <Integer>).

ArrayList<String> noms = new ArrayList<>();
Liste vide de String
noms.add("Lina");
Ajoute à la fin
noms.get(0)
Élément d'indice 0
noms.size()
Nombre d'éléments
noms.remove(0);
Supprime l'élément d'indice 0
noms.contains("Lina")
Teste la présence d'un élément
Liste.java
import java.util.ArrayList;

public class Liste {
    public static void main(String[] args) {
        ArrayList<String> noms = new ArrayList<>();

        noms.add("Lina");
        noms.add("Sami");
        noms.add("Nova");
        noms.remove(1);

        System.out.println(noms);
        System.out.println(noms.size() + " " + noms.get(0) + " " + noms.contains("Sami"));
    }
}
Affichage
[Lina, Nova]
2 Lina false

HashMap et HashSet

Map · Set

Une Map associe une clé à une valeur (comme un dictionnaire Python) ; un Set ne garde qu'un exemplaire de chaque élément.

HashMap<String, Integer> notes = new HashMap<>();
Association nom → note
notes.put("Lina", 15);
Ajoute, ou remplace si la clé existe déjà
notes.get("Lina")
Valeur de la clé, ou null si elle est absente
notes.getOrDefault("Zoe", 0)
Valeur, ou 0 si la clé est absente
notes.containsKey("Lina")
Teste la présence d'une clé
HashSet<Integer> s = new HashSet<>();
Ensemble sans doublon
Notes.java
import java.util.HashMap;
import java.util.HashSet;

public class Notes {
    public static void main(String[] args) {
        HashMap<String, Integer> notes = new HashMap<>();
        notes.put("Lina", 15);
        notes.put("Sami", 12);
        notes.put("Lina", 17);                  // remplace l'ancienne valeur

        System.out.println(notes.get("Lina"));
        System.out.println(notes.getOrDefault("Zoe", 0));
        System.out.println(notes.size());

        HashSet<Integer> uniques = new HashSet<>();
        uniques.add(3);
        uniques.add(3);
        uniques.add(5);
        System.out.println(uniques.size());
    }
}
Affichage
17
0
2
2

📚 Le cours : les structures de données prêtes à l'emploi

Un tableau a une taille fixe et peu d'opérations. Le paquetage java.util fournit des collections : des structures de données déjà écrites, qui grandissent à la demande et offrent des méthodes pour ajouter, chercher, supprimer.

CollectionCe qu'elle faitQuand la choisir
ArrayList<T>liste ordonnée, accès par indicele choix par défaut pour une suite d'éléments
HashMap<K, V>association clé → valeur, recherche très rapideretrouver une valeur à partir d'une clé (nom → note)
HashSet<T>ensemble sans doublontester l'appartenance, supprimer les doublons
TreeMap, TreeSetcomme HashMap / HashSet, mais triésparcourir dans l'ordre des clés
ArrayDeque<T>pile (LIFO) ou file (FIFO)empiler / défiler

Les génériques : le type entre chevrons

ArrayList<String> ne contient que des String : le compilateur refuse d'y ajouter autre chose et dispense de convertir à la lecture. Les chevrons n'acceptent que des classes, pas les types primitifs : on écrit ArrayList<Integer> (et non ArrayList<int>). Java convertit automatiquement int ⇄ Integer (*boxing*), de même pour double ⇄ Double, char ⇄ Character.

Parcourir, trier, modifier une ArrayList

On parcourt avec un for-each ou avec un indice (liste.get(i), de 0 à liste.size() - 1). Collections.sort(liste) trie en place ; set(i, valeur) remplace un élément.

Parcours.java
import java.util.ArrayList;
import java.util.Collections;

public class Parcours {
    public static void main(String[] args) {
        ArrayList<Integer> nombres = new ArrayList<>();
        nombres.add(5);
        nombres.add(2);
        nombres.add(9);

        Collections.sort(nombres);
        int somme = 0;
        for (int n : nombres) {
            somme += n;
        }
        System.out.println(nombres + " somme = " + somme);

        nombres.set(0, 100);
        System.out.println(nombres);
    }
}
Affichage
[2, 5, 9] somme = 16
[100, 5, 9]

Supprimer des éléments en filtrant

Modifier une liste pendant un for-each lève une ConcurrentModificationException. Pour supprimer selon un critère, utilise removeIf avec une condition écrite sous forme de lambda (n -> n % 2 == 0 se lit « pour chaque n, n pair »).

Filtre.java
import java.util.ArrayList;

public class Filtre {
    public static void main(String[] args) {
        ArrayList<Integer> nombres = new ArrayList<>();
        for (int i = 1; i <= 10; i++) {
            nombres.add(i);
        }

        nombres.removeIf(n -> n % 2 == 0);
        System.out.println(nombres);
    }
}
Affichage
[1, 3, 5, 7, 9]

Compter avec une Map

Une Map est idéale pour compter : la clé est l'élément, la valeur est son nombre d'occurrences. getOrDefault(c, 0) + 1 évite de tester si la clé existe. Un HashMap ne garantit aucun ordre de parcours ; un TreeMap parcourt les clés dans l'ordre croissant.

Frequences.java
import java.util.Map;
import java.util.TreeMap;

public class Frequences {
    public static void main(String[] args) {
        String texte = "abracadabra";
        TreeMap<Character, Integer> freq = new TreeMap<>();

        for (char c : texte.toCharArray()) {
            freq.put(c, freq.getOrDefault(c, 0) + 1);
        }
        for (Map.Entry<Character, Integer> e : freq.entrySet()) {
            System.out.println(e.getKey() + " : " + e.getValue());
        }
    }
}
Affichage
a : 5
b : 2
c : 1
d : 1
r : 2

C'est l'équivalent du dictionnaire Python : dans les deux cas, une table de hachage rend la recherche d'une clé très rapide.

Supprimer les doublons avec un Set

Un Set ignore l'ajout d'un élément déjà présent. new TreeSet<>(collection) construit en plus un ensemble trié.

Doublons.java
import java.util.Arrays;
import java.util.TreeSet;

public class Doublons {
    public static void main(String[] args) {
        Integer[] valeurs = {4, 8, 4, 15, 8, 16};
        TreeSet<Integer> uniques = new TreeSet<>(Arrays.asList(valeurs));

        System.out.println(uniques);
        System.out.println(uniques.contains(15));
    }
}
Affichage
[4, 8, 15, 16]
true

Tableau ou ArrayList ?

Un tableau (int[]) est plus rapide et accepte les types primitifs, mais sa taille est figée. Une ArrayList s'agrandit seule (elle remplace son tableau interne par un plus grand quand il est plein, comme avec realloc en C) et fournit add, remove, contains, mais ne contient que des objets.

⚠️ Erreurs fréquentes

remove(int) ou remove(Object) ?

Sur une ArrayList<Integer>, remove(1) supprime l'élément d'indice 1, pas la valeur 1. Pour supprimer une valeur, passe un objet.

Retrait.java
import java.util.ArrayList;
import java.util.Arrays;

public class Retrait {
    public static void main(String[] args) {
        ArrayList<Integer> l = new ArrayList<>(Arrays.asList(5, 6, 7));

        l.remove(1);                       // supprime l'élément d'INDICE 1
        System.out.println(l);
        l.remove(Integer.valueOf(7));      // supprime la VALEUR 7
        System.out.println(l);
    }
}
Affichage
[5, 7]
[5]

Un type primitif entre les chevrons

À éviter
Faux.java
ArrayList<int> notes = new ArrayList<>();       // erreur de compilation
Correct
Correct.java
ArrayList<Integer> notes = new ArrayList<>();   // classe enveloppe

Modifier une liste pendant son parcours

À éviter
Faux.java
for (int n : nombres) {
    if (n % 2 == 0) {
        nombres.remove(Integer.valueOf(n));   // ConcurrentModificationException
    }
}
Correct
Correct.java
nombres.removeIf(n -> n % 2 == 0);       // suppression sûre

Comparer des Integer avec ==

Integer a = 1000, b = 1000; a == b vaut false : on compare deux objets. (Pour de petites valeurs, entre −128 et 127, Java réutilise les objets et == « marche », ce qui cache le bug.) Utilise a.equals(b).

get sur une clé absente

notes.get("Zoe") renvoie null si la clé n'existe pas ; écrire int n = notes.get("Zoe"); lève alors une NullPointerException à la conversion. Utilise getOrDefault ou teste containsKey.

Supposer un ordre dans un HashMap ou un HashSet

Leur ordre de parcours n'est pas garanti et peut changer d'une version de Java à l'autre. Si l'ordre compte, choisis TreeMap / TreeSet (trié) ou LinkedHashMap (ordre d'insertion).

Essayer de modifier List.of(…)

List.of(1, 2, 3) crée une liste non modifiable : add lève une UnsupportedOperationException. Écris new ArrayList<>(List.of(1, 2, 3)) pour obtenir une liste modifiable.

📋 Aide-mémoire

  • ArrayList<T> : add, get(i), set(i, x), remove(i), size(), contains, Collections.sort.
  • HashMap<K, V> : put, get (ou getOrDefault), containsKey, entrySet() ; HashSet<T> : add, contains, pas de doublon.
  • TreeMap / TreeSet : mêmes méthodes, parcours dans l'ordre ; HashMap / HashSet : aucun ordre garanti.
  • Types primitifs interdits entre chevrons : Integer, Double, Character… (conversion automatique).
  • Supprimer en parcourant : removeIf(...), jamais remove dans un for-each.
  • liste.remove(1) supprime l'indice 1 ; liste.remove(Integer.valueOf(1)) supprime la valeur 1.