CodeGym /Cours /JAVA 25 SELF /Nouvelles collections : SequencedCollection, Sequenc...

Nouvelles collections : SequencedCollection, SequencedSet, SequencedMap

JAVA 25 SELF
Niveau 34, Leçon 4
Disponible

1. Le problème de l’ordre dans les collections classiques

En Java, il y a toujours eu des collections qui garantissent l’ordre des éléments (par exemple, ArrayList, LinkedList, LinkedHashSet, LinkedHashMap) et d’autres où l’ordre n’est pas garanti (par exemple, HashSet, HashMap). Mais toutes ces collections avaient un inconvénient commun : bien que certaines conservent un ordre déterminé des éléments, les interfaces standard (List, Set, Map) ne fournissaient pas de méthodes universelles pour accéder aux premiers et derniers éléments ou inverser l’ordre.

Par exemple, si vous avez un List<String>, vous pouvez obtenir le premier élément via list.get(0), mais pour un Set ou une Map, cette astuce ne fonctionne pas — il faut utiliser des itérateurs ou écrire du code supplémentaire. Convenez que ce n’est ni très pratique ni favorable à la lisibilité.

C’est comme si vous aviez une armoire à tiroirs, mais que pour sortir le premier ou le dernier tiroir, vous deviez recompter tous les tiroirs à chaque fois ! Il serait bien plus agréable d’avoir des poignées « premier » et « dernier », non ?

Apparition de SequencedCollection et des interfaces associées

Dans Java 21, de nouvelles interfaces de collections sont apparues :

  • SequencedCollection<E>
  • SequencedSet<E>
  • SequencedMap<K, V>

Ces interfaces étendent les collections standard et introduisent une approche unifiée pour travailler avec l’ordre des éléments. On peut désormais écrire du code universel pour n’importe quelles collections où l’ordre compte, sans se soucier de l’implémentation concrète.

De quoi s’agit-il ?

  • SequencedCollection — une collection où les éléments ont un ordre défini, et où vous pouvez facilement obtenir le premier et le dernier élément, ainsi qu’inverser l’ordre.
  • SequencedSet — la même idée, mais pour les ensembles (éléments uniques).
  • SequencedMap — la même idée, mais pour les mappages (clé-valeur).

Quelles collections les implémentent désormais ?

Dans Java 21, les nouvelles interfaces sont implémentées par les collections standard suivantes :

  • ArrayList, LinkedListSequencedCollection
  • LinkedHashSet, TreeSetSequencedSet
  • LinkedHashMap, TreeMapSequencedMap

Cela signifie que si vous utilisez déjà ces collections, vous bénéficiez automatiquement de ces nouvelles possibilités !

2. Méthodes principales de SequencedCollection, SequencedSet, SequencedMap

Méthodes de SequencedCollection

E getFirst();      // Obtenir le premier élément
E getLast();       // Obtenir le dernier élément
SequencedCollection<E> reversed(); // Obtenir la collection en ordre inverse

Méthodes de SequencedSet

Les mêmes méthodes que SequencedCollection, plus tout ce que fait Set.

Méthodes de SequencedMap

Map.Entry<K, V> firstEntry();    // Premier élément (clé-valeur)
Map.Entry<K, V> lastEntry();     // Dernier élément (clé-valeur)
SequencedMap<K, V> reversed();   // Map en ordre inverse

3. Exemples d’utilisation des nouvelles interfaces

Exemple 1 : obtenir le premier et le dernier élément

import java.util.*;

public class SequencedDemo {
    public static void main(String[] args) {
        SequencedCollection<String> sc = new ArrayList<>();
        sc.add("Java");
        sc.add("Python");
        sc.add("Kotlin");

        // Obtenir le premier et le dernier élément
        String first = sc.getFirst(); // "Java"
        String last = sc.getLast();   // "Kotlin"

        System.out.println("Premier: " + first);
        System.out.println("Dernier: " + last);
    }
}

Sortie :

Premier: Java
Dernier: Kotlin

Exemple 2 : inversion de la collection

SequencedCollection<String> sc = new LinkedList<>();
sc.add("A");
sc.add("B");
sc.add("C");

SequencedCollection<String> reversed = sc.reversed();
System.out.println(reversed); // [C, B, A]

À noter : reversed() renvoie une vue de la collection en ordre inverse. Si vous modifiez la collection d’origine, la vue inversée changera aussi !

Exemple 3 : travail avec SequencedSet

SequencedSet<Integer> set = new LinkedHashSet<>();
set.add(100);
set.add(200);
set.add(300);

System.out.println("Premier élément: " + set.getFirst()); // 100
System.out.println("Dernier élément: " + set.getLast()); // 300

SequencedSet<Integer> reversedSet = set.reversed();
System.out.println(reversedSet); // [300, 200, 100]

Exemple 4 : travail avec SequencedMap

SequencedMap<String, Integer> map = new LinkedHashMap<>();
map.put("apple", 5);
map.put("banana", 3);
map.put("cherry", 7);

Map.Entry<String, Integer> first = map.firstEntry();
Map.Entry<String, Integer> last = map.lastEntry();

System.out.println("Premier: " + first.getKey() + " = " + first.getValue()); // apple = 5
System.out.println("Dernier: " + last.getKey() + " = " + last.getValue()); // cherry = 7

SequencedMap<String, Integer> reversedMap = map.reversed();
System.out.println(reversedMap); // {cherry=7, banana=3, apple=5}

4. Quel lien avec votre application ?

Supposons que, dans votre application pédagogique, vous stockiez la liste des utilisateurs qui se sont connectés et que vous vouliez obtenir rapidement le premier et le dernier utilisateur (par exemple, pour afficher « qui s’est connecté en premier » et « qui est le dernier »). Auparavant, il fallait écrire quelque chose comme :

List<String> users = new ArrayList<>();
// ... on ajoute des utilisateurs
String first = users.get(0);
String last = users.get(users.size() - 1);

Mais si la collection n’est pas une liste, et par exemple un LinkedHashSet (où les éléments sont uniques et l’ordre est conservé), cette astuce ne fonctionne plus :

Set<String> users = new LinkedHashSet<>();
// ... on ajoute des utilisateurs
// Comment obtenir le premier ? Uniquement via un itérateur :
String first = users.iterator().next();
// Et le dernier ? Il faut parcourir tous les éléments !

Désormais, c’est plus simple et plus universel :

SequencedSet<String> users = new LinkedHashSet<>();
// ... on ajoute des utilisateurs
String first = users.getFirst();
String last = users.getLast();

Cela réduit non seulement la quantité de code, mais le rend également plus lisible et plus sûr.

5. Schéma des nouvelles interfaces

classDiagram
    Collection <|-- SequencedCollection
    List <|-- SequencedCollection
    Set <|-- SequencedSet
    Map <|-- SequencedMap
    SequencedCollection <|-- SequencedSet
    SequencedSet <|-- LinkedHashSet
    SequencedSet <|-- TreeSet
    SequencedCollection <|-- ArrayList
    SequencedCollection <|-- LinkedList
    SequencedMap <|-- LinkedHashMap
    SequencedMap <|-- TreeMap

6. Points utiles

Avantages pratiques de SequencedCollection

  • Interface unifiée pour gérer l’ordre : Plus besoin de se souvenir où get(0) existe, où un itérateur est nécessaire, et où il est impossible d’obtenir le premier élément.
  • Pratique avec les files et les piles : Obtenez facilement l’élément de tête (head) et de queue (tail).
  • Sécurité et lisibilité : Moins d’erreurs liées à une utilisation incorrecte des collections ; le code devient auto-documenté.
  • Inversion rapide de la collection : La méthode reversed() permet d’obtenir facilement l’ordre inverse sans manipulations manuelles.
  • Simplicité de maintenance et d’évolution du code : Si, à l’avenir, vous souhaitez remplacer par exemple un ArrayList par un LinkedHashSet, le code utilisant SequencedCollection n’aura pas à être réécrit.

Particularités d’implémentation

  • Toutes les collections n’implémentent pas SequencedCollection : Par exemple, HashSet et HashMap ne garantissent pas l’ordre, ils n’implémentent donc pas ces nouvelles interfaces.
  • Les méthodes peuvent lever des exceptions : Si la collection est vide, appeler getFirst() ou getLast() provoquera une NoSuchElementException. N’oubliez pas de vérifier que la collection n’est pas vide !
  • reversed() — c’est une vue, pas une copie : Les modifications de la collection d’origine se reflètent dans la vue inversée, et inversement.
  • Compatibilité : Les nouvelles interfaces sont disponibles uniquement à partir de Java 21. Si vous utilisez une version de Java plus ancienne, ces fonctionnalités ne sont pas disponibles (c’est une excellente raison de mettre à jour !).
  • Génériques : Toutes les nouvelles interfaces prennent pleinement en charge les génériques, vous pouvez donc travailler avec n’importe quel type de données.

7. Erreurs courantes avec SequencedCollection

Erreur n° 1 : Attendre la prise en charge de l’ordre de collections qui ne le garantissent pas. Si vous essayez de caster un HashSet en SequencedSet, vous aurez une erreur de compilation — HashSet n’a pas d’ordre et n’implémente pas cette interface.

Erreur n° 2 : Ignorer les collections vides. Appeler getFirst() ou getLast() sur une collection vide lèvera une exception. Avant d’utiliser ces méthodes, vérifiez que la collection n’est pas vide :

if (!sc.isEmpty()) {
    String first = sc.getFirst();
}

Erreur n° 3 : Malentendus autour de reversed(). La méthode reversed() renvoie une vue, pas une copie. Si vous modifiez la vue inversée, la collection d’origine changera également (et inversement). Cela peut mener à des résultats inattendus si vous ne vous attendez pas à ce comportement.

Erreur n° 4 : Utiliser les nouvelles interfaces sur d’anciennes versions de Java. Si votre projet est compilé avec une version inférieure à Java 21, le compilateur ne trouvera pas ces interfaces. Vérifiez la version du JDK dans les paramètres du projet !

1
Mission
JAVA 25 SELF, niveau 34, leçon 4
Bloqué
Gestionnaire de tâches intelligent: vérification du vide avant de travailler 🤖
Gestionnaire de tâches intelligent: vérification du vide avant de travailler 🤖
1
Mission
JAVA 25 SELF, niveau 34, leçon 4
Bloqué
Algorithme des étapes : commande directe et inversée 🔄
Algorithme des étapes : commande directe et inversée 🔄
1
Étude/Quiz
Collections modernes, niveau 34, leçon 4
Indisponible
Collections modernes
Collections modernes et immutabilité
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION