Les listes dynamiques - java.util.ArrayList

13 Sep 2019 13 Sep 2019 15080 vues ESSADDOUKI Mostafa 19 min de lecture
Introduction
1 Nouveautés de Java 11 2 Différences entre JDK, JRE et JVM 3 Structure d'un programme Java - Hello World 4 Mots clés et conventions de dénomination en Java 5 Types de données intégrés en Java 6 Les variables en Java 7 Classes enveloppe - Number, Integer, Double ... 8 Lire les entrées clavier en Java
Structures de contrôle
9 Les opérateurs en Java 10 Les structures conditionnelles en Java 11 Les boucles en Java 12 Instructions de contrôle de boucle - break, continue
Chaines de caractères
13 Les chaines en Java - API String 14 Les chaines en Java - StringBuffer et StringBuilder 15 Les expressions régulières en Java
Programmation OO
16 Objets et classes en Java 17 Modificateurs d'accès Java - public, private, protected et package 18 Méthodes et surcharge des méthodes en Java 19 les constructeurs en Java 20 L'héritage en Java 21 Classes abstraites en Java 22 Interfaces et héritage multiple en Java 23 Les classes imbriquées en Java 24 Les singletons en Java 25 Classes et méthodes génériques 26 Interface fonctionnelle et expressions Lambda en Java
Tableaux et collections
27 Les tableaux en Java 28 Classe Arrays - java.util.Arrays 29 Les listes dynamiques - java.util.ArrayList 30 Les listes chaînées en Java - java.util.LinkedList 31 HashSet en Java - java.util.HashSet 32 HashMap en Java - java.util.HashMap
Gestion des fichiers
33 Comprendre les fichiers informatiques 34 Utilisation des classes Path et Files en Java 35 Lecture et écriture dans un fichier en Java 36 Fichiers à accès aléatoire en Java
Gestion d'exceptions
37 Gestion d'exceptions en Java 38 Créez vos propres classes d'exception en Java
Programmation concurrente
39 Introduction à la programmation concurrente en Java - Multi-threads 40 classe java.lang.Thread 41 Synchronisation des threads en Java
Cours Java pour les débutants — Étape 29 sur 41

ArrayList — Listes dynamiques en Java

  Prérequis

Maîtriser les tableaux classiques et la classe Arrays. Comprendre les types génériques (diamond operator <>). Connaître les classes wrapper (Integer, Double, etc.).

  Objectifs

Comprendre l'intérêt des listes dynamiques par rapport aux tableaux classiques. Maîtriser la création, l'ajout, la suppression, la modification et le parcours d'une ArrayList. Connaître les différences fondamentales entre tableaux et ArrayList.

1. Qu'est-ce qu'une ArrayList ?

ArrayList

ArrayList est une classe du Java Collections Framework qui implémente une liste dynamique redimensionnable. Contrairement aux tableaux classiques, sa taille peut changer pendant l'exécution du programme — elle s'agrandit automatiquement lors de l'ajout d'éléments et se contracte lors de leur suppression.

La classe ArrayList offre plusieurs avantages par rapport aux tableaux classiques :

  • Taille dynamique : pas besoin de connaître la taille à l'avance
  • Ajout automatique : la capacité s'adapte automatiquement
  • Suppression flexible : les éléments peuvent être supprimés à tout moment
  • Méthodes puissantes : add(), remove(), get(), set(), size(), etc.
Types primitifs et ArrayList

ArrayList ne peut contenir que des objets, pas des types primitifs. Pour stocker des valeurs primitives (int, double, boolean, etc.), on utilise les classes wrapper (Integer, Double, Boolean, etc.). L'autoboxing convertit automatiquement les primitifs en objets.

2. Déclaration et création

   
Syntaxe — Déclaration d'une ArrayList Java
import java.util.ArrayList;  // ou import java.util.*;

// Capacité par défaut : 10
ArrayList<String> noms = new ArrayList<String>();

// Version simplifiée (diamond operator) — Java 7+
ArrayList<String> noms = new ArrayList<>();

// Avec capacité initiale
ArrayList<String> noms = new ArrayList<>(20);

// À partir d'une autre collection
ArrayList<Integer> nombres = new ArrayList<>(Arrays.asList(1, 2, 3));

  Exemple 1 — Déclaration et création

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        // ArrayList de chaînes de caractères
        ArrayList<String> noms = new ArrayList<>();

        // ArrayList d'entiers (utilise Integer, pas int)
        ArrayList<Integer> notes = new ArrayList<>();

        // ArrayList d'objets personnalisés
        ArrayList<Etudiant> etudiants = new ArrayList<>();

        System.out.println("Liste créée avec succès");
    }
}
Capacité initiale

Le constructeur par défaut crée une ArrayList avec une capacité de 10 éléments. La capacité est le nombre d'éléments qu'elle peut contenir sans avoir à s'agrandir. Si vous savez que vous aurez besoin de plus d'éléments, il est plus efficace de spécifier une capacité initiale plus grande.

3. Méthodes principales

Méthode Description Complexité
boolean add(E e) Ajoute un élément à la fin de la liste O(1) amorti
void add(int index, E element) Insère un élément à une position spécifique O(n)
E remove(int index) Supprime l'élément à l'index spécifié O(n)
boolean remove(Object o) Supprime la première occurrence de l'objet O(n)
E set(int index, E element) Remplace l'élément à l'index spécifié O(1)
E get(int index) Retourne l'élément à l'index spécifié O(1)
int size() Retourne le nombre d'éléments O(1)
boolean isEmpty() Vérifie si la liste est vide O(1)
void clear() Supprime tous les éléments O(n)
boolean contains(Object o) Vérifie si un élément existe O(n)
int indexOf(Object o) Retourne l'index de la première occurrence O(n)

4. Ajout d'éléments — add()

  Exemple 2 — Ajout d'éléments

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> liste = new ArrayList<>();

        // Ajout à la fin
        liste.add(4);
        liste.add(5);
        liste.add(2);
        System.out.println("Après ajouts : " + liste);

        // Insertion à une position spécifique
        liste.add(0, 1);  // Insère 1 à l'index 0
        System.out.println("Après insertion : " + liste);

        // Ajout de plusieurs éléments
        liste.addAll(Arrays.asList(10, 20, 30));
        System.out.println("Après addAll : " + liste);
    }
}
Sortie
Après ajouts : [4, 5, 2]
Après insertion : [1, 4, 5, 2]
Après addAll : [1, 4, 5, 2, 10, 20, 30]

5. Suppression d'éléments — remove()

  Exemple 3 — Suppression d'éléments

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> fruits = new ArrayList<>();
        fruits.add("Pomme");
        fruits.add("Banane");
        fruits.add("Orange");
        fruits.add("Pomme");
        fruits.add("Kiwi");

        System.out.println("Liste originale : " + fruits);

        // Suppression par index
        fruits.remove(1);  // Supprime "Banane"
        System.out.println("Après remove(1) : " + fruits);

        // Suppression par objet (première occurrence)
        fruits.remove("Pomme");
        System.out.println("Après remove('Pomme') : " + fruits);

        // Suppression de tous les éléments
        fruits.clear();
        System.out.println("Après clear() : " + fruits);
        System.out.println("Est vide ? " + fruits.isEmpty());
    }
}
Sortie
Liste originale : [Pomme, Banane, Orange, Pomme, Kiwi]
Après remove(1) : [Pomme, Orange, Pomme, Kiwi]
Après remove('Pomme') : [Orange, Pomme, Kiwi]
Après clear() : []
Est vide ? true

6. Accès et modification — get() et set()

  Exemple 4 — Lecture et modification

import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> notes = new ArrayList<>();
        notes.add(12);
        notes.add(15);
        notes.add(18);
        notes.add(14);

        // Accès par get()
        System.out.println("Note à l'index 1 : " + notes.get(1));

        // Parcours classique
        System.out.print("Toutes les notes : ");
        for (int i = 0; i < notes.size(); i++) {
            System.out.print(notes.get(i) + " ");
        }
        System.out.println();

        // Modification avec set()
        notes.set(2, 20);  // Remplace 18 par 20
        System.out.println("Après modification : " + notes);
    }
}
Sortie
Note à l'index 1 : 15
Toutes les notes : 12 15 18 14 
Après modification : [12, 15, 20, 14]

7. Parcours d'une ArrayList

  Exemple 5 — Différentes façons de parcourir

import java.util.ArrayList;
import java.util.Iterator;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> langages = new ArrayList<>();
        langages.add("Java");
        langages.add("Python");
        langages.add("JavaScript");
        langages.add("C++");

        // 1. Boucle for classique
        System.out.println("=== Boucle for classique ===");
        for (int i = 0; i < langages.size(); i++) {
            System.out.println(langages.get(i));
        }

        // 2. Boucle for-each (recommandée)
        System.out.println("\n=== Boucle for-each ===");
        for (String lang : langages) {
            System.out.println(lang);
        }

        // 3. Avec Iterator
        System.out.println("\n=== Iterator ===");
        Iterator<String> it = langages.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        // 4. Avec forEach() + lambda (Java 8+)
        System.out.println("\n=== forEach() avec lambda ===");
        langages.forEach(lang -> System.out.println(lang));
    }
}

8. Tri d'une ArrayList — Collections.sort()

  Exemple 6 — Tri avec Collections.sort()

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

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

        System.out.println("Liste non triée : " + nombres);

        // Tri en ordre croissant
        Collections.sort(nombres);
        System.out.println("Liste triée croissant : " + nombres);

        // Tri en ordre décroissant
        Collections.sort(nombres, Collections.reverseOrder());
        System.out.println("Liste triée décroissant : " + nombres);

        // Tri personnalisé avec lambda (Java 8+)
        ArrayList<String> mots = new ArrayList<>(Arrays.asList("banane", "apple", "cerise", "date"));
        mots.sort((a, b) -> a.compareTo(b));
        System.out.println("Mots triés : " + mots);
    }
}
Sortie
Liste non triée : [4, 5, 2, 9, 1]
Liste triée croissant : [1, 2, 4, 5, 9]
Liste triée décroissant : [9, 5, 4, 2, 1]
Mots triés : [apple, banane, cerise, date]

9. ArrayList avec objets personnalisés

  Exemple 7 — ArrayList d'étudiants

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

class Etudiant implements Comparable<Etudiant> {
    private String nom;
    private double moyenne;

    public Etudiant(String nom, double moyenne) {
        this.nom = nom;
        this.moyenne = moyenne;
    }

    public String getNom() { return nom; }
    public double getMoyenne() { return moyenne; }

    @Override
    public String toString() {
        return String.format("%s (%.2f)", nom, moyenne);
    }

    @Override
    public int compareTo(Etudiant autre) {
        return Double.compare(autre.moyenne, this.moyenne); // Tri par moyenne décroissante
    }
}

public class Test {
    public static void main(String[] args) {
        ArrayList<Etudiant> promotion = new ArrayList<>();
        promotion.add(new Etudiant("Mostafa", 16.5));
        promotion.add(new Etudiant("Amal", 18.0));
        promotion.add(new Etudiant("Youssef", 14.5));
        promotion.add(new Etudiant("Fatima", 17.2));

        System.out.println("=== Liste originale ===");
        for (Etudiant e : promotion) {
            System.out.println(e);
        }

        // Tri selon compareTo
        Collections.sort(promotion);

        System.out.println("\n=== Liste triée par moyenne (décroissante) ===");
        for (Etudiant e : promotion) {
            System.out.println(e);
        }
    }
}
Sortie
=== Liste originale ===
Mostafa (16.50)
Amal (18.00)
Youssef (14.50)
Fatima (17.20)

=== Liste triée par moyenne (décroissante) ===
Amal (18.00)
Fatima (17.20)
Mostafa (16.50)
Youssef (14.50)

10. Tableau comparatif — Array vs ArrayList

Caractéristique Array (tableau) ArrayList
Taille Fixe (déterminée à la création) Dynamique (redimensionnable automatiquement)
Types supportés Primitifs et objets Objets uniquement (avec autoboxing pour primitifs)
Syntaxe d'accès tableau[index] liste.get(index)
Syntaxe de modification tableau[index] = valeur liste.set(index, valeur)
Ajout d'éléments Non possible (taille fixe) add() — dynamique
Suppression d'éléments Non possible (taille fixe) remove() — décalage automatique
Dimension array.length (attribut) list.size() (méthode)
Performance Plus rapide (accès direct) Légèrement plus lent (méthodes + redimensionnement)
Type générique Non applicable Oui (ArrayList<E>)
Stockage en mémoire
  • Array de primitifs : les valeurs réelles sont stockées dans des emplacements contigus.
  • Array d'objets : les références sont stockées dans des emplacements contigus, les objets sont ailleurs.
  • ArrayList : fonctionne comme un tableau d'objets — les références sont stockées de façon contiguë, les objets réels sont sur le tas.

11. Conversion entre Array et ArrayList

  Exemple 8 — Conversions

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        // Array → ArrayList
        String[] tableau = {"A", "B", "C", "D"};
        ArrayList<String> liste = new ArrayList<>(Arrays.asList(tableau));
        System.out.println("Array → ArrayList : " + liste);

        // ArrayList → Array
        String[] nouveauTableau = liste.toArray(new String[0]);
        System.out.println("ArrayList → Array : " + Arrays.toString(nouveauTableau));

        // Version Java 8+ : Stream
        int[] nombres = {1, 2, 3, 4, 5};
        ArrayList<Integer> listeNombres = Arrays.stream(nombres)
                                                .boxed()
                                                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
        System.out.println("Primitifs → ArrayList : " + listeNombres);
    }
}
Sortie
Array → ArrayList : [A, B, C, D]
ArrayList → Array : [A, B, C, D]
Primitifs → ArrayList : [1, 2, 3, 4, 5]

12. Exemple complet — Gestion d'une liste de tâches

  Exemple 9 — Application de gestion de tâches

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class GestionTaches {
    private ArrayList<String> taches;

    public GestionTaches() {
        taches = new ArrayList<>();
    }

    public void ajouterTache(String tache) {
        taches.add(tache);
        System.out.println("✓ Tâche ajoutée : " + tache);
    }

    public void supprimerTache(int index) {
        if (index >= 0 && index < taches.size()) {
            String supprimee = taches.remove(index);
            System.out.println("✗ Tâche supprimée : " + supprimee);
        } else {
            System.out.println("Index invalide !");
        }
    }

    public void marquerCompletee(int index) {
        if (index >= 0 && index < taches.size()) {
            String tache = taches.get(index);
            taches.set(index, "✓ " + tache);
            System.out.println("✓ Tâche complétée : " + tache);
        } else {
            System.out.println("Index invalide !");
        }
    }

    public void afficherTaches() {
        if (taches.isEmpty()) {
            System.out.println("Aucune tâche dans la liste.");
            return;
        }
        System.out.println("\n=== LISTE DES TÂCHES ===");
        for (int i = 0; i < taches.size(); i++) {
            System.out.printf("%d. %s%n", i + 1, taches.get(i));
        }
        System.out.println("Total : " + taches.size() + " tâche(s)\n");
    }

    public void trierTaches() {
        Collections.sort(taches);
        System.out.println("Tâches triées alphabétiquement.");
    }

    public static void main(String[] args) {
        GestionTaches gestion = new GestionTaches();
        Scanner scanner = new Scanner(System.in);
        int choix;

        do {
            System.out.println("\n=== MENU ===");
            System.out.println("1. Ajouter une tâche");
            System.out.println("2. Supprimer une tâche");
            System.out.println("3. Marquer une tâche comme complétée");
            System.out.println("4. Afficher toutes les tâches");
            System.out.println("5. Trier les tâches");
            System.out.println("6. Quitter");
            System.out.print("Votre choix : ");
            choix = scanner.nextInt();
            scanner.nextLine();  // Consommer le saut de ligne

            switch (choix) {
                case 1:
                    System.out.print("Nom de la tâche : ");
                    String tache = scanner.nextLine();
                    gestion.ajouterTache(tache);
                    break;
                case 2:
                    gestion.afficherTaches();
                    System.out.print("Numéro de la tâche à supprimer : ");
                    int indexSuppr = scanner.nextInt() - 1;
                    gestion.supprimerTache(indexSuppr);
                    break;
                case 3:
                    gestion.afficherTaches();
                    System.out.print("Numéro de la tâche à compléter : ");
                    int indexComplete = scanner.nextInt() - 1;
                    gestion.marquerCompletee(indexComplete);
                    break;
                case 4:
                    gestion.afficherTaches();
                    break;
                case 5:
                    gestion.trierTaches();
                    break;
                case 6:
                    System.out.println("Au revoir !");
                    break;
                default:
                    System.out.println("Choix invalide !");
            }
        } while (choix != 6);

        scanner.close();
    }
}

13. Exercice

Gestionnaire de contacts

Niveau : Intermédiaire

Créer une application de gestion de contacts utilisant ArrayList.

Travail demandé

  1. Créer une classe Contact avec les attributs : nom, prenom, telephone, email.
  2. Créer une classe GestionnaireContacts avec une ArrayList<Contact>.
  3. Implémenter les méthodes :
    • ajouterContact(Contact c)
    • supprimerContact(int index)
    • modifierContact(int index, Contact nouveau)
    • rechercherParNom(String nom) — retourne tous les contacts dont le nom contient la chaîne
    • trierParNom() — tri alphabétique
    • afficherTous()
  4. Créer un menu console pour tester l'application.

  L'essentiel en bref

Synthèse — ArrayList
  • ArrayList est une liste dynamique redimensionnable du Java Collections Framework.
  • Elle ne peut contenir que des objets (l'autoboxing convertit automatiquement les primitifs).
  • Création : ArrayList<Type> nom = new ArrayList<>();
  • Ajout : add(element) (à la fin) ou add(index, element) (à une position).
  • Suppression : remove(index) ou remove(Object).
  • Accès : get(index) — modification : set(index, element).
  • Taille : size() (méthode, pas attribut).
  • Tri : Collections.sort(liste) (nécessite Comparable ou Comparator).
  • Parcours : for-each, for classique, iterator, forEach() avec lambda.
  • Différence clé avec les tableaux : taille dynamique, méthodes intégrées, objets uniquement.
Un peu d'histoire

ArrayList a été introduite dans Java 1.2 (1998) avec le Java Collections Framework, une refonte majeure des structures de données en Java. Contrairement à Vector (qui existe depuis Java 1.0), ArrayList n'est pas synchronisée, ce qui la rend plus performante pour les applications mono-thread. L'introduction des génériques en Java 5 (2004) a permis de typer ArrayList avec ArrayList<E>, éliminant les casts dangereux. Java 8 a ajouté l'API Stream et les méthodes forEach(), removeIf(), etc. Aujourd'hui, ArrayList est l'une des collections les plus utilisées en Java.

Sortie
// La sortie apparaîtra ici…
Prêt · Ctrl+Entrée pour exécuter

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.