0Pricing
Java Academy · Leçon

Contrats d’Iterable et d’Iterator

Comprenez les interfaces Iterable et Iterator ainsi que le fonctionnement interne des boucles for-each.

Contrats d’Iterable et d’Iterator est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.

Iterable et Iterator

Iterable<T> et Iterator<T> sont les interfaces qui permettent la boucle Java pour chaque élément. Les comprendre vous permet de rendre vos propres structures de données compatibles avec ce type de boucle.

L’interface Iterable

Iterable<T> possède une méthode : iterator(), qui renvoie un Iterator<T>. Toute classe implémentant Iterable peut être utilisée dans une boucle pour chaque élément.

// java.lang.Iterable<T>
interface Iterable<T> {
    Iterator<T> iterator();
    // default: forEach, spliterator (Java 8+)
}

// Any class implementing Iterable<T> works in for-each:
class Range implements Iterable<Integer> {
    private final int start, end;
    Range(int start, int end) { this.start = start; this.end = end; }

    public Iterator<Integer> iterator() {
        return new RangeIterator(); // defined separately
    }
}

L’interface Iterator

Iterator<T> possède trois méthodes : hasNext(), next() et la méthode facultative remove().

// java.util.Iterator<T>
interface Iterator<T> {
    boolean hasNext(); // true if more elements
    T next();          // returns next element, advances cursor
    default void remove() { throw new UnsupportedOperationException(); }
}

// How for-each desugars internally:
// for (T item : iterable) { use(item); }
// becomes:
Iterator<T> it = iterable.iterator();
while (it.hasNext()) {
    T item = it.next();
    // use(item)
}

Déroulement de la boucle pour chaque élément

La boucle pour chaque élément est du sucre syntaxique autour du motif Iterable/Iterator. Comprendre ce fonctionnement vous aide à écrire correctement vos propres Iterables.

List<String> names = List.of("Alice", "Bob", "Charlie");

// For-each (readable way)
for (String name : names) {
    System.out.println(name);
}

// Equivalent explicit form
Iterator<String> it = names.iterator();
while (it.hasNext()) {
    String name = it.next();
    System.out.println(name);
}

État du curseur d’Iterator

Un Iterator conserve un curseur, c’est-à-dire une position dans la séquence. L’appel à next() fait avancer le curseur. Une fois arrivé à la fin, l’iterator ne peut pas être réinitialisé.

List<Integer> nums = List.of(1, 2, 3);
Iterator<Integer> it = nums.iterator();

System.out.println(it.hasNext()); // true
System.out.println(it.next());    // 1
System.out.println(it.next());    // 2
System.out.println(it.next());    // 3
System.out.println(it.hasNext()); // false

try {
    it.next(); // NoSuchElementException
} catch (java.util.NoSuchElementException e) {
    System.out.println("No more elements!");
}

ConcurrentModificationException

Modifier une collection pendant son parcours avec un iterator explicite, en dehors de Iterator.remove(), déclenche ConcurrentModificationException.

List<String> list = new ArrayList<>(List.of("a", "b", "c", "d"));

// BAD: modifying collection during for-each
try {
    for (String s : list) {
        if ("b".equals(s)) list.remove(s); // ConcurrentModificationException!
    }
} catch (java.util.ConcurrentModificationException e) {
    System.out.println("Cannot modify during iteration!");
}

// GOOD: use Iterator.remove()
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if ("b".equals(it.next())) it.remove(); // safe
}
System.out.println(list); // [a, c, d]

Plusieurs Iterators

Chaque appel à iterator() renvoie un iterator nouveau et indépendant. Plusieurs iterators peuvent être actifs simultanément sur la même collection.

List<Integer> nums = List.of(1, 2, 3);

Iterator<Integer> a = nums.iterator();
Iterator<Integer> b = nums.iterator();

System.out.println(a.next()); // 1
System.out.println(b.next()); // 1 (independent cursor)
System.out.println(a.next()); // 2
System.out.println(b.next()); // 2

Iterable ou Iterator

Distinction essentielle :

  • Iterable : une source capable de produire des iterators ; elle peut être parcourue plusieurs fois
  • Iterator : un curseur sur une séquence ; il est utilisable une seule fois et conserve un état
// Iterable: reusable
List<String> list = List.of("x", "y");
for (String s : list) {} // OK
for (String s : list) {} // OK again — new iterator each time

// Iterator: single-use
Iterator<String> it = list.iterator();
while (it.hasNext()) it.next();
// for (String s : it) {} // compile error — Iterator is not Iterable!

Pratique : Iterable personnalisé pour les lignes d’un fichier

Un lecteur de fichiers qui implémente Iterable afin de permettre une boucle pour chaque élément sur ses lignes.

import java.io.*;
import java.util.*;

class FileLines implements Iterable<String>, Closeable {
    private final BufferedReader reader;

    FileLines(String path) throws IOException {
        this.reader = new BufferedReader(new FileReader(path));
    }

    public Iterator<String> iterator() {
        return new Iterator<>() {
            private String nextLine = readNext();

            private String readNext() {
                try { return reader.readLine(); }
                catch (IOException e) { return null; }
            }

            public boolean hasNext() { return nextLine != null; }
            public String next() {
                String curr = nextLine;
                nextLine = readNext();
                return curr;
            }
        };
    }

    public void close() throws IOException { reader.close(); }
}

Méthode par défaut forEach

Java 8 a ajouté à Iterable une méthode forEach(Consumer) par défaut. Elle offre une solution pratique pour éviter d’écrire des boucles explicites.

List<String> cities = List.of("New York", "London", "Tokyo");

// for-each loop
for (String city : cities) System.out.println(city);

// forEach with lambda
cities.forEach(city -> System.out.println(city));

// forEach with method reference (most concise)
cities.forEach(System.out::println);

// For transforming: use stream
cities.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println);

Le motif Iterator en pratique

Résumé des situations où implémenter Iterable/Iterator :

  • Structures de données personnalisées (arbre, graphe, liste chaînée)
  • Séquences différées qui génèrent les éléments à la demande
  • Séquences fondées sur des ressources (lignes d’un fichier, curseur de base de données, file de messages)

Vérification rapide

Quelle exception est déclenchée lorsque vous modifiez une collection pendant son parcours avec une boucle pour chaque élément ?

Récapitulatif : contrats d’Iterable et d’Iterator

Points essentiels :

  • Iterable<T> possède une méthode : iterator() — elle permet l’utilisation dans une boucle pour chaque élément
  • Iterator<T> possède hasNext(), next() et remove(), qui est facultative
  • La boucle pour chaque élément est du sucre syntaxique autour du motif Iterable/Iterator
  • Appelez iterator() plusieurs fois pour obtenir des curseurs indépendants et nouveaux
  • Ne modifiez jamais une collection pendant une boucle pour chaque élément — utilisez Iterator.remove() à la place
  • Implémentez Iterable pour les structures de données personnalisées afin de prendre en charge les boucles pour chaque élément

Questions Fréquemment Posées

La leçon « Contrats d’Iterable et d’Iterator » est-elle gratuite ?

Oui — le texte complet de « Contrats d’Iterable et d’Iterator » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Contrats d’Iterable et d’Iterator » ?

Comprenez les interfaces Iterable et Iterator ainsi que le fonctionnement interne des boucles for-each. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Java Academy ?

Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Contrats d’Iterable et d’Iterator » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?

Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Contrats d’Iterable et d’Iterator
  2. Implémenter un itérateur personnalisé
  3. ListIterator et parcours bidirectionnel
  4. Itérateurs à échec rapide et tolérants aux modifications
← Retour à Java Academy