Aller au contenu

Découvrez les collections en java

Ce sont des classes qui permettent de stocker, manipuler et parcourir des groupes d’objets. Par la même occasion, nous verrons la notion d’interface.

collections en java

Il existe plusieurs types de Collection qui ont chacune leurs propres caractéristiques et utilisations. Nous allons en découvrir quelques unes dans ce cours.

Listes (implémentation de List)

Une liste est un ensemble ordonné d’éléments qui peuvent se répéter.

Il existe plusieurs implémentations de listes :

Exemple de code :

List<String> liste = new ArrayList<>();
liste.add("Java");
liste.add("C++");
liste.add("Python");
System.out.println(liste); // affiche "[Java, C++, Python]"

Laquelle utiliser entre LinkedList et ArrayList ?

La LinkedList est une implémentation de List qui utilise des liens entre les éléments pour stocker les données.

Principe : Chaque élément contient une référence à l’élément précédent et suivant, permettant ainsi de parcourir la liste dans les deux sens. Elle permet d’insérer ou supprimer des éléments à n’importe quelle position dans la liste, mais elle rend les accès aléatoires plus lents que dans une ArrayList.

Remarque : C’est pratique si vous devez souvent insérer ou supprimer des éléments à des positions spécifiques de la liste, ou si vous devez parcourir la liste dans les deux sens. Cependant, attention, si vous avez besoin d’accéder fréquemment à des éléments spécifiques de la liste, il est préférable d’utiliser une ArrayList car elle sera plus rapide pour les accès aléatoires.

Petit exemple concret en utilisant une LinkedList pour stocker une liste d’entiers :

LinkedList<Integer> liste = new LinkedList<>();
liste.add(1);
liste.add(2);
liste.add(3);
liste.add(4);

System.out.println(liste); // affiche : [1, 2, 3, 4]

liste.add(1, 5);
System.out.println(liste); // affiche : [1, 5, 2, 3, 4]

liste.remove(2);
System.out.println(liste); // affiche : [1, 5, 3, 4]

La liste de course

Si je fais une liste de course, quelle liste utiliser ? ArrayList ou LinkedList ?

Les 2 sont possibles, tout dépend de ce que l’on souhaite manipuler.

Si on choisit une ArrayList, elle sera plus rapide pour les opérations d’accès par index, car elle utilise un tableau interne pour stocker les éléments. mais, elle sera plus lente pour les opérations d’ajout et de suppression, car il faut déplacer les éléments suivants lorsqu’un élément est ajouté ou supprimé au milieu de la liste.

Si on utilise la LinkedList, sachant qu’elle utilise des noeuds pour stocker les éléments, elle sera plus lente pour les opérations d’accès par index, mais plus rapide pour les opérations d’ajout et de suppression. Ce type de LinkedList est particulièrement utile lorsqu’on doit ajouter ou supprimer des éléments de manière fréquente soit en début de liste, soit en fin de la liste !

On va stocker notre liste de course dans une ArrayList :

import java.util.ArrayList;

public class ListeCourses {

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

        listeCourses.add("Pain");
        listeCourses.add("Lait");
        listeCourses.add("PQ");
        listeCourses.add("Oeufs");
        listeCourses.add("Beurre");

        // Affiche la liste de courses
        System.out.println("Liste de courses : " + listeCourses);

        // Ajout d'un élément à la fin de la liste
        listeCourses.add("Fruits");
        System.out.println("Liste de courses : " + listeCourses);

        // Suppression d'un élément de la liste
        listeCourses.remove("Lait");
        System.out.println("Liste de courses : " + listeCourses);
    }
}

Maintenant, on va stocker notre liste de course dans une LinkedList :

import java.util.LinkedList
...

LinkedList<String> listeCourses = new LinkedList<>();
listeCourses.add("Pommes");
listeCourses.add("Poires");
listeCourses.add("Bananes");
listeCourses.add("Ordinateur");
listeCourses.add("Lait");

System.out.println("Liste de courses : " + listeCourses);

// Ajout d'un élément à la fin de la liste
listeCourses.addLast("Pain");
System.out.println("Liste de courses avec pain ajouté : " + listeCourses);

// Ajout d'un élément au début de la liste
listeCourses.addFirst("Beurre");
System.out.println("Liste de courses avec beurre ajouté : " + listeCourses);

// Suppression d'un élément
listeCourses.remove("Poires");
System.out.println("Liste de courses après suppression des poires : " + listeCourses);

Cette dernière (LinkedList) est une liste doublement liée !

L’intérêt du Linked est que chaque noeud possède des informations sur le noeud précédent s’il existe et le noeud suivant s’il y en a un. Commme je le précise un peu plus loin, on peut naviguer dans les 2 sens au sein de ce type de collection.

En fin de compte, la LinkedList permet d’insérer ou de supprimer des éléments rapidement à n’importe quel emplacement de la liste.

C’est donc une bonne option pour les utilisations qui nécessitent de nombreuses opérations d’insertion et de suppression, comme dans l’exemple de notre liste de courses !

En revanche, si vous avez besoin de rechercher fréquemment des éléments dans une liste, il est préférable d’utiliser une ArrayList plus rapide pour les recherches car elle utilise un tableau pour stocker les éléments.

Ensembles (Set) : Elements uniques

C’est un ensemble non ordonné d’éléments uniques.

Il existe plusieurs implémentations d’ensembles :

Exemple de code :

Set<Integer> set = new HashSet<>();
set.add(5);
set.add(7);
set.add(5); // 5 ne sera pas ajouté car déjà présent, ouf ! donc pas besoin de contrôler
System.out.println(set); // affichera {5, 7}

Implémentation de Deque (ou file) - interface

C’est une liste d’éléments qui respecte un ordre d’arrivée et de sortie le fameux FIFO (First In, First Out, soit Premier entré, premier sorti) ne pas confondre avec la FIFA !

Il existe 2 implémentations :

Exemple de code :

Queue<String> queue = new ArrayDeque<>();
queue.add("Java");
queue.add("C++");
queue.add("Python");
System.out.println(queue.poll()); // affiche : Java et retire l'élément de la queue
System.out.println(queue.poll()); // affiche : C++ et le retire de la queue

Map (Interface)

C’est une collection permettant de stocker des paires clé-valeur.

Il existe plusieurs implémentations de Map :

Différences entre HashMap et LinkedHashMap

La HashMap et la LinkedHashMap sont toutes les deux des implémentations de l’interface Map.

La principale différence entre les deux est l’ordre des éléments.

La HashMap est optimisée pour les opérations de recherche et de suppression, mais pas pour les opérations d’itération !

Voici un exemple de code pour créer une HashMap :

HashMap<String, Integer> monMap = new HashMap<>();
monMap.put("Clé1", 1);
monMap.put("Clé2", 2);
monMap.put("Clé3", 3);

La LinkedHashMap stocke ses éléments dans l’ordre dans lequel ils ont été ajoutés. ça veut dire qu’elle maintient une liste chaînée des éléments ce qui permet une itération dans l’ordre d’insertion.

Attention : Ce n’est pas conseillé pour les opérations de recherche et de suppression (plus lentes qu’avec la HashMap) !

Voici un exemple de code pour créer une LinkedHashMap et ajouter des éléments :

LinkedHashMap<String, Integer> monMap = new LinkedHashMap<>();
monMap.put("Clé1", 1);
monMap.put("Clé2", 2);
monMap.put("Clé3", 3);

En résumé :

Question : Comment sait-on que la HashMap ne garantie pas l’ordre des éléments ajoutés ? en quoi cela est-il gênant ?

La HashMap utilise une fonction de hachage pour stocker ses éléments. Cette fonction prend en compte la clé de l’élément pour le stocker à un emplacement précis dans la table de hachage. Cependant, ça veut dire que l’ordre dans lequel les éléments ont été ajoutés n’est pas pris en compte lors du stockage. Ainsi, lorsque l’on parcourt les éléments d’une HashMap, ils peuvent être retournés dans un ordre différent de celui dans lequel ils ont été ajouté !

Attention : Cela peut être gênant dans les cas où l’ordre dans lequel les éléments ont été ajoutés est important !

Exemple : Si vous utilisez une HashMap pour stocker les étapes d’un processus, et que vous voulez les parcourir dans l’ordre où ils ont été ajoutés. Dans ce cas, il est préférable d’utiliser une LinkedHashMap qui maintient l’ordre d’insertion des éléments !

C’est quoi une table de Hashage ?

Une table de hachage est une structure de données qui utilise une fonction de hachage pour associer des clés à des valeurs.

Le but de cette fonction est de transformer la clé en un indice de table de sorte qu’on puisse accéder rapidement à la valeur correspondante.

La table de hachage est souvent utilisée pour implémenter des tableaux associatifs (comme en Php), des caches, des index de base de données, etc.

Elles sont souvent plus rapides que les structures de données alternatives pour les opérations de recherche, d’insertion et de suppression, car elles ont un temps d’accès constant.

Exemple :

A chaque fois qu’une clé est ajoutée à une table de hachage, elle est d’abord passée à travers une fonction de hachage qui génère un index ou un emplacement où la valeur associée à cette clé sera stockée.

Du coup, lorsqu’une valeur est recherchée dans la table, la clé est à nouveau passée à travers la fonction de hachage pour trouver l’emplacement où la valeur est stockée.

Exemple d’utilisation d’une HashMap :

HashMap<String, Integer> notes = new HashMap<>();
// ajout de quelques éléments à la HashMap
notes.put("Marie", 15);
notes.put("Paul", 12);
notes.put("Lucie", 18);
notes.put("Mathieu", 14);

// affichage de tous les éléments
// ici on récupère des objets de type Map.Entry pour récupérer
// la clef et la valeur en même temps. C'est un peu fastidieux à écrire.
for (Map.Entry<String, Integer> entry : notes.entrySet()) {
    System.out.println(entry.getKey() + " : " + entry.getValue());
}

// ou de cette manière, plus simplement
// avec une boucle foreach()
for( String key : notes.keyset())
{
    System.out.println(key + " : " + notes.get(key));
}

Explication :

Approfondissement HashMap : getOrDefault()

getOrDefault(), une méthode bien pratique.

V getOrDefault(Object key, V defaultValue)

Voici comment utiliser getOrDefault() dans le code ci-dessous pour gérer le cas où un client n’est pas trouvé !

// Map : recherche rapide par clé
Map<String, Client> clients = new HashMap<>();
// Instanciation de 2 objets clients
Client c1 = new Client("CLI001", "Depp", 2500.0);
Client c2 = new Client("CLI002", "Foster", 3500.0);

// On stocke les références de nos clients associés à leur code
clients.put(c1.getCode(), c1); // "CLI001" pour c1
clients.put(c2.getCode(), c2); // "CLI002" pour c2

// recherche du client par le code (la clé)
String codeATrouver = "CLI001";
System.out.println("On recherche le client ayant le code " + codeATrouver + " : ");
Client clientTrouve = clients.getOrDefault(codeATrouver, new Client("INCONNU", "Client Inconnu", 0.0));

// affichage du résultat
if (clientTrouve.getCode().equals("INCONNU")) {
    System.out.println("Client non trouvé. Retourne un client par défaut : " + clientTrouve.getNom());
} else {
    System.out.println("Client trouvé : " + clientTrouve.getNom());
}

// exemple avec une clé inexistante
String codeInexistant = "CLI999";
Client clientInexistant = clients.getOrDefault(codeInexistant, new Client("INCONNU", "Client Inconnu", 0.0));
System.out.println("Recherche d'un client inexistant (CLI999) : " + clientInexistant.getNom());

Explications :

Problème avec getOrDefault() et les Objets Inutiles et solutions

Dans cette écriture Client client = clients.getOrDefault("CLI999", new Client("INCONNU", "Client Inconnu", 0.0)); vous avez certainement remarqué que cela nous oblige a instancier un objet inutile ! Ce qui serait une mauvaise pratique si notre code était inclus dans une boucle !

// problème : Un nouvel objet "Client Inconnu" est créé à chaque appel, même s'il n'est pas utilisé !
Client client = clients.getOrDefault("CLI999", new Client("INCONNU", "Client Inconnu", 0.0));

Impact :

Solutions Alternatives

Voici 4 approches pour éviter ce problème, classées par ordre de préférence (de la plus simple à la plus avancée).

Solution 1 : Utiliser une constante statique

Créer une seule instance du client “inconnu” et la réutiliser.

// une constante statique pour le client "inconnu"
private static final Client CLIENT_INCONNU = new Client("INCONNU", "Client Inconnu", 0.0);
// Utilisation
Client client = clients.getOrDefault("CLI999", CLIENT_INCONNU);

Avantages :

Inconvénients :

Solution 2 : Vérifier d’abord avec containsKey()

Utiliser containsKey() pour vérifier l’existence de la clé avant de créer un objet par défaut.

// vérifier d'abord si la clé existe
Client client;
if (clients.containsKey("CLI999")) {
    client = clients.get("CLI999");
} else {
    client = new Client("INCONNU", "Client Inconnu", 0.0);  // créé uniquement si nécessaire
}

Avantages :

Inconvénients :

Solution 3 : Utiliser computeIfAbsent() (Java 8+)

La méthode computeIfAbsent() permet de créer un objet par défaut uniquement si la clé est absente, et de le stocker dans la map pour les appels futurs.

// computeIfAbsent() crée l'objet uniquement si la clé est absente
Client client = clients.computeIfAbsent("CLI999", k -> new Client("INCONNU", "Client Inconnu", 0.0));

Avantages :

Inconvénients :

Solution 4 : Utiliser un Objet “Null” ou Optional

Retourner null ou un Optional pour indiquer qu’une clé est absente, puis gérer le cas manuellement.

Approche courante :

// retourner null et gérer le cas manuellement
Client client = clients.get("CLI999");
if (client == null) {
    client = new Client("INCONNU", "Client Inconnu", 0.0);  // Créé uniquement si nécessaire
}

Approche plus moderne avec Optional (Java 8+) :

// utiliser Optional pour une approche plus moderne
Client client = Optional.ofNullable(clients.get("CLI999"))
    .orElse(new Client("INCONNU", "Client Inconnu", 0.0));

Avantages :

Inconvénients :

Conclusion

Il n’y a pas de solution miracle, la première solution avec une constante statique est certainement la plus simple et la plus efficace.

Exercice de mise en pratique

Pour voir si vous avez compris voici un énoncé d’un petit exercice de mise en pratique, mais quelle solution allez-vous choisir ?

Solution :

import java.util.HashMap;
import java.util.Map;

public class Main {
    // produit "inconnu" statique
    private static final Produit PRODUIT_INCONNU = new Produit("INCONNU", 0.0);

    public static void main(String[] args) {
        Map<String, Produit> produits = new HashMap<>();
        produits.put("P001", new Produit("Pomme", 1.5));
        produits.put("P002", new Produit("Banane", 0.99));

        // recherche de produits
        String[] codes = {"P001", "P002", "P999"};
        for (String code : codes) {
            Produit produit = produits.getOrDefault(code, PRODUIT_INCONNU);
            System.out.printf("Produit %s: %s (%.2f€)%n",
                code, produit.getNom(), produit.getPrix());
        }
    }
}

class Produit {
    private String nom;
    private double prix;

    public Produit(String nom, double prix) {
        this.nom = nom;
        this.prix = prix;
    }

    public String getNom() { return nom; }
    public double getPrix() { return prix; }
}

Résultat attendu :

Produit P001: Pomme (1,50€)
Produit P002: Banane (0,99€)
Produit P999: INCONNU (0,00€)

Parcourir avec entrySet()

La méthode entrySet() permet de parcourir les paires clé-valeur (Map.Entry) de la map. C’est la méthode la plus efficace et la plus lisible.

Exemple :

// parcourir la Map avec entrySet()
for (Map.Entry<String, Double> entry : totalParVille.entrySet()) {
    String ville = entry.getKey();      // Clé (nom de la ville)
    Double totalVentes = entry.getValue();  // Valeur (total des ventes)
    System.out.println("Ville: " + ville + ", Total des ventes: " + totalVentes);
}

Avantages :

Parcourir avec keySet()

La méthode keySet() permet de parcourir uniquement les clés de la map. On peut ensuite récupérer la valeur associée avec get().

Exemple :

// Parcourir la map avec keySet()
for (String ville : totalParVille.keySet()) {
    Double totalVentes = totalParVille.get(ville);
    System.out.println("Ville: " + ville + ", Total des ventes: " + totalVentes);
}

Avantages :

Inconvénients :

Parcourir avec forEach() (Java 8+)

La méthode forEach() permet de parcourir la map de manière fonctionnelle en utilisant une lambda. C’est très pratique pour des opérations simples.

Exemple :

// Parcourir la map avec forEach() et une lambda
totalParVille.forEach((ville, totalVentes) -> {
    System.out.println("Ville: " + ville + ", Total des ventes: " + totalVentes);
});

Avantages :

Cas d’usage :

Parcourir avec values()

La méthode values() permet de parcourir uniquement les valeurs de la map. Utile si vous n’avez pas besoin des clés.

Exemple :

// Parcourir uniquement les valeurs (totaux des ventes)
for (Double totalVentes : totalParVille.values()) {
    System.out.println("Total des ventes: " + totalVentes);
}

Avantages :

Inconvénients : Pas d’accès aux clés (On ne sait pas à quelle ville correspond chaque total !).

Utiliser un Iterator (Moins courant)

Bien que moins utilisé depuis Java 8, on peut parcourir une map avec un Iterator. Cela peut être utile dans certains cas spécifiques (suppression d’éléments pendant le parcours).

Exemple :

// Parcourir la map avec un Iterator
Iterator<Map.Entry<String, Double>> iterator = totalParVille.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<String, Double> entry = iterator.next();
    String ville = entry.getKey();
    Double totalVentes = entry.getValue();
    System.out.println("Ville: " + ville + ", Total des ventes: " + totalVentes);
}

Cas d’usage :

Exemple complet

// Supposons que tu as déjà cette map :
Map<String, Double> totalParVille = ventes.stream()
    .collect(Collectors.groupingBy(Vente::getVille, Collectors.summingDouble(Vente::getMontant)));

// Méthode 1 : entrySet() (recommandée)
System.out.println("--- Méthode 1 : entrySet() ---");
for (Map.Entry<String, Double> entry : totalParVille.entrySet()) {
    System.out.printf("Ville: %-15s | Total: %.2f%n", entry.getKey(), entry.getValue());
}

// Méthode 2 : keySet()
System.out.println("\n--- Méthode 2 : keySet() ---");
for (String ville : totalParVille.keySet()) {
    System.out.printf("Ville: %-15s | Total: %.2f%n", ville, totalParVille.get(ville));
}

// Méthode 3 : forEach() (Java 8+)
System.out.println("\n--- Méthode 3 : forEach() ---");
totalParVille.forEach((ville, totalVentes) ->
    System.out.printf("Ville: %-15s | Total: %.2f%n", ville, totalVentes)
);

// Méthode 4 : values() (si tu n'as besoin que des totaux)
System.out.println("\n--- Méthode 4 : values() ---");
for (Double totalVentes : totalParVille.values()) {
    System.out.printf("Total des ventes: %.2f%n", totalVentes);
}

Cas concret : Calculer la Moyenne des Ventes par Ville

Si on veut calculer la moyenne des ventes par ville, on peut combiner entrySet() avec un autre stream :

// Supposons que nous ayons une map du nombre de ventes par ville
Map<String, Long> nombreVentesParVille = ventes.stream()
    .collect(Collectors.groupingBy(Vente::getVille, Collectors.counting()));

// calcul de la moyenne par ville
System.out.println("\n--- Moyenne des ventes par ville ---");
for (Map.Entry<String, Double> entry : totalParVille.entrySet()) {
    String ville = entry.getKey();
    Double totalVentes = entry.getValue();
    Long nombreVentes = nombreVentesParVille.get(ville);
    double moyenne = totalVentes / nombreVentes;
    System.out.printf("Ville: %-15s | Moyenne: %.2f%n", ville, moyenne);
}

Conlusion sur les modes de parcours

Bonnes pratiques pour parcourir une HashMap

Bonnes Pratiques Exemple
Préférer entrySet() for (Map.Entry<String, Double> entry : map.entrySet()) (meilleure performance).
Utiliser forEach() pour du code concis map.forEach((k, v) -> System.out.println(k + ": " + v)).
Éviter get() dans une boucle Utilise entrySet() plutôt que keySet() + get() pour éviter des accès inutiles à la map.
Utiliser values() si seules les valeurs sont nécessaires for (Double value : map.values()).
Utiliser Iterator pour modifier la map pendant le parcours iterator.remove() pour supprimer un élément en toute sécurité.

Méthodes de parcours d’une HashMap

Méthode Syntaxe Cas d’Usage
entrySet() for (Map.Entry<K, V> entry : map.entrySet()) Parcours clé-valeur (recommandé pour la plupart des cas).
keySet() for (K key : map.keySet()) Parcours des clés uniquement (si les valeurs ne sont pas nécessaires).
forEach() map.forEach((k, v) -> { ... }) Style fonctionnel (Java 8+), idéal pour des opérations simples.
values() for (V value : map.values()) Parcours des valeurs uniquement (si les clés ne sont pas nécessaires).
Iterator Iterator<Map.Entry<K, V>> it = map.entrySet().iterator(); while (it.hasNext()) { ... } Parcours avec possibilité de modification (suppression) pendant l’itération.

Récapitulatif des Collections en Java

Liste de quelques unes des méthodes fréquemment utilisées

Liste de méthodes spécifiques selon les Collections

Comment fonctionnent PriorityQueue et ArrayDeque ?

Elle permet de stocker des éléments en respectant un ordre de priorité. Cet ordre est défini en fonction de la méthode compareTo() des éléments contenus dans la PriorityQueue. Si cette méthode n’est pas surchargée, donc redéfinie, les éléments seront triés en fonction de leur ordre naturel.

Exemple de code :

PriorityQueue<Integer> queue = new PriorityQueue<>();
queue.offer(30);
queue.offer(20);
queue.offer(10);
System.out.println(queue.poll()); // affiche 10
System.out.println(queue.poll()); // affiche 20
System.out.println(queue.poll()); // affiche 30

Elle permet de stocker des éléments de manière doublement chaînée, ça veut dire qu’on peut ajouter et supprimer des éléments à la fois au début et à la fin de ArrayDeque. Cette classe permet un accès rapide aux éléments du début et de la fin de la collection mais sans la possibilité de donner une priorité comme avec PriorityDeque.

Pour info, Deque est une abréviation qui veut dire Double-Ended Queue (file à double extrémité ou entrée en français). C’est une interface de la bibliothèque standard de Java qui définit un type de données permettant de stocker une série d’éléments ordonnés avec la possibilité d’ajouter ou retirer des éléments à la fois en tête et en queue. Cette interface permet de manipuler des éléments de la fil avec une certaine flexibilité.

Exemple :

ArrayDeque<String> deque = new ArrayDeque<>();
deque.addFirst("Premier");
deque.addFirst("Milieu");
deque.addLast("Dernier");
System.out.println(deque.pop()); // affiche le Premier
System.out.println(deque.pollLast()); // affiche le Dernier

En gros, si vous voulez un ordre d’éléments dans une collection, vous pouvez utiliser PriorityQueue, si vous voulez un accès rapide aux éléments du début et de la fin de la collection, vous pouvez utiliser ArrayDeque.

PriorityQueue<Task> tasks = new PriorityQueue<>();
tasks.add(new Task("Tâche 1", Priority.HIGH));
tasks.add(new Task("Tâche 2", Priority.MEDIUM));
tasks.add(new Task("Tâche 3", Priority.LOW));

Task task = tasks.poll();
System.out.println("Tâche en tête de file : " + task.getName()); // affiche : Tâche en tête de file : Tâche 1

Ci-dessus, on crée une file d’attente de tâches avec des priorities différentes avec la méthode poll() qui récupére la tâche de plus haute priority et la supprimer de la file d’attente.

Comment la méthode poll() supprime l’élément ?

La méthode poll() de PriorityQueue et ArrayDeque supprime et renvoie l’élément en tête de la file. Cela signifie que c’est l’élément qui a la priorité la plus élevée dans la file de priorité (PriorityQueue) ou l’élément en tête de la file (ArrayDeque) qui est supprimé !

PriorityQueue est basée sur l’ordre naturel de ses éléments (si aucun comparateur n’est spécifié) ou sur le comparateur spécifié lors de sa création.

Pour ArrayDeque, cela supprime l’élément de tête de la file.

Exemple :

PriorityQueue<Integer> pq = new PriorityQueue<>();
pq.offer(5);
pq.offer(3);
pq.offer(1);
pq.offer(4);
pq.offer(2);
int element = pq.poll();
System.out.println("l'element en tête de file est : " + element);

Ci-dessus, l’élément en tête de file est 1 qui est supprimé de la file.

ArrayDeque<Integer> arrayDeque = new ArrayDeque<>();
arrayDeque.add(5);
arrayDeque.add(3);
arrayDeque.add(1);
int element = arrayDeque.poll();
System.out.println("l'element en tête de file est : " + element);

Ci-dessus, l’élément en tête de file est 5 qui est supprimé de la file.

Conclusion

En conclusion, les collections en Java offrent une variété d’options pour stocker et organiser les données de différentes manières en fonction de vos besoins, et il est important de comprendre leurs différentes fonctionnalités et utilisations pour choisir la meilleure option pour votre application !