- Apprendre
- Informatique et numérique
- Programmation
- Java orienté objet : classes, collections, héritage et tests
- HashMap et collections en Java
HashMap et collections en Java
HashMap, à compter et à regrouper des valeurs, et à conserver des valeurs distinctes avec HashSet. Découvre les garanties des interfaces List, Set et Map, trie des listes, donne un ordre naturel à tes propres classes avec Comparable et choisis la collection adaptée à chaque tâche.DébutantUnité 7 sur 11 de la formation Formation : Java orienté objet : classes, collections, héritage et tests
Ce que tu vas apprendre
- Crée des Map de hachage, ajoute, lis, mets à jour et supprime des paires clé–valeur, parcours le contenu d’une Map et utilise tes propres classes comme clés que la Map peut retrouver.
- Crée une HashMap, puis ajoute, consulte, mets à jour et supprime des entréesDéclare une HashMap avec ses types de clé et de valeur, stocke des paires avec put, lis-les avec get et traite les clés absentes.
- Parcours les clés, les valeurs et les entréesParcours chaque paire d’une Map avec keySet, values et entrySet, identifie l’ordre possible et modifie une Map sans erreur pendant son parcours.
- Utilise tes propres objets comme clés de MapRends les objets de tes propres classes utilisables comme clés en redéfinissant equals et hashCode ensemble, et ne modifie pas les clés tant qu’elles sont dans une Map.
- Crée une HashMap, puis ajoute, consulte, mets à jour et supprime des entrées
- Utilise des Map pour compter les occurrences, réunir des valeurs liées sous une même clé et construire des tables de correspondance qui retrouvent rapidement des objets.
- Compte les occurrences et calcule les sommes par cléConstruis des tableaux des effectifs et des sommes cumulées avec le schéma getOrDefault, puis lis correctement les résultats.
- Regroupe des valeurs sous une même clé en utilisant des listes et des ensembles comme valeursConstruis des Map dont les valeurs sont des listes ou des ensembles, ajoute les éléments au bon groupe et évite les erreurs qui font perdre ou endommagent des groupes.
- Recherche rapidement des objets et des prix avec un index fondé sur une MapUtilise des Map comme tables de correspondance et index pour trouver des objets par une clé unique, conserve-les dans une classe et maintiens la cohérence entre plusieurs index.
- Compte les occurrences et calcule les sommes par clé
- Utilise HashSet pour stocker des valeurs sans doublons, teste rapidement l’appartenance et combine des ensembles par union, intersection et différence.
- Stocke des valeurs distinctes et teste l’appartenance avec HashSetAjoute, vérifie et supprime des valeurs dans une HashSet, utilise le résultat de add et supprime les doublons d’une liste.
- Combine des ensembles et préserve leur ordreCalcule des unions, des intersections et des différences sans modifier les ensembles d’origine, compare des ensembles et choisis un ensemble ordonné lorsque l’ordre compte.
- Stocke des valeurs distinctes et teste l’appartenance avec HashSet
- Déclare les collections avec leurs types interface, identifie les garanties de chaque interface et utilise les méthodes communes aux différentes implémentations.
- Déclare des variables et des paramètres de type interfaceExplique ce qu’est un type interface, déclare des collections comme List, Set ou Map et écris des méthodes qui acceptent toute implémentation.
- Identifie les garanties de List, Set et MapCompare les garanties des trois interfaces, reconnais leurs principales implémentations et manipule des collections non modifiables créées avec of.
- Déclare des variables et des paramètres de type interface
- Trie des listes dans l’ordre naturel, donne un ordre naturel à tes propres classes en implémentant Comparable et utilise cet ordre dans des ensembles et des Map triés.
- Trie des listes de nombres et de chaînesTrie une liste en place avec Collections.sort, prévois l’ordre des chaînes et trie dans l’ordre inverse ou sans tenir compte de la casse.
- Implémente Comparable dans ta propre classeDonne un ordre naturel à une classe en implémentant Comparable et en écrivant compareTo avec des comparaisons sûres de nombres et de chaînes.
- Départage les égalités et utilise des ensembles et des Map triésOrdonne des objets selon plusieurs champs, assure la cohérence de compareTo avec equals et utilise TreeSet et TreeMap pour conserver des données triées.
- Trie des listes de nombres et de chaînes
- Compare la vitesse des opérations courantes dans chaque collection et choisis le type adapté à ce que le programme doit faire avec ses données.
- Compare le coût des opérations courantes sur les collectionsEstime comment le temps des recherches, des insertions et des suppressions augmente avec la taille de chaque collection, et repère les schémas lents.
- Choisis une collection qui répond aux besoins de la tâcheRéponds à quelques questions sur l’ordre, les doublons et la recherche pour choisir entre tableaux, listes, ensembles et Map, puis combine-les pour des données plus complexes.
- Compare le coût des opérations courantes sur les collections
HashMap et collections en Java : cours
1Stocke et recherche des données par clé avec HashMap
Un code produit peut mener directement à une quantité en stock, sans parcourir une liste. Les Map rendent ce lien explicite, mais pour bien les utiliser, il faut aussi traiter les clés absentes, parcourir les paires sans erreur et définir quand deux objets servant de clés sont considérés comme égaux. Commence par une petite Map de stocks, puis suis les changements de son contenu et la façon dont Java retrouve une clé stockée. Les mêmes règles d’égalité compteront lorsque tu utiliseras des ensembles.
1.1 Crée une HashMap, puis ajoute, consulte, mets à jour et supprime des entrées
Une Map stocke une association entre chaque clé et une valeur. Dans une Map de stocks, un nom de produit est la clé et sa quantité est la valeur. Deux produits peuvent avoir la même quantité, mais une clé de produit ne peut pas correspondre à deux entrées distinctes.
Créer la Map
import java.util.HashMap;
HashMap<String, Integer> stock = new HashMap<>();
Le premier type, String, décrit les clés. Le second, Integer, décrit les valeurs. Le diamant <> à droite permet à Java de déduire ces types. Les arguments de type doivent être des types référence : utilise Integer, Double, Character ou Boolean au lieu de int, double, char ou boolean. Java effectue l’autoboxing d’un simple int lorsqu’il le stocke comme Integer, et l’unboxing d’un Integer lorsqu’un int est nécessaire.
Suivre chaque modification
stock.put("apple", 12);
stock.put("pear", 7);
Integer previous = stock.put("apple", 15);
Le premier appel crée apple=12 ; le deuxième ajoute pear=7. Le troisième trouve la clé "apple" existante et remplace sa valeur. La Map contient maintenant deux entrées et previous contient 12. Un appel à put pour une clé sans association précédente renvoie null.
stock.get("apple") renvoie maintenant 15. stock.remove("pear") renvoie 7 et supprime cette entrée. Une nouvelle suppression de "pear" renvoie null. size() compte les entrées, isEmpty() vérifie s’il n’y en a aucune et clear() les supprime toutes.
Traiter une clé absente
stock.get("kiwi") renvoie null et stock.containsKey("kiwi") renvoie false. Cette instruction se compile mais échoue à l’exécution :
int quantity = stock.get("kiwi");
Java essaie d’effectuer l’unboxing de null en int, ce qui provoque une NullPointerException. Pour une Map de quantités non nulles, utilise une valeur par défaut :
int quantity = stock.getOrDefault("kiwi", 0);
Cela donne 0 sans ajouter "kiwi" à la Map. Tu peux aussi vérifier avec containsKey avant la lecture. containsValue(15) vérifie si une entrée possède cette valeur ; la méthode peut parcourir toutes les valeurs, ce qui diffère de la recherche d’une clé connue.
Une HashMap autorise aussi une clé null et des valeurs null. Si une clé est explicitement associée à null, getOrDefault renvoie ce null stocké, et non la valeur par défaut. containsKey distingue ce cas d’une clé absente. Les Map de quantités sont plus simples lorsque chaque quantité stockée est une valeur numérique plutôt que null.
Faire correspondre correctement les clés et les valeurs
Les clés de type String sont sensibles à la casse : "apple", "Apple" et "apple " sont différentes. Applique le même nettoyage avant le stockage et la recherche, par exemple avec name.trim().toLowerCase(). Nettoyer uniquement une clé de recherche ne peut pas corriger des clés stockées de façon incohérente.
Compare le contenu des valeurs enveloppées avec equals. Si deux entrées contiennent chacune 1000, leurs références Integer peuvent être différentes : == peut donc être faux même si leurs contenus numériques correspondent. Après avoir vérifié que les deux valeurs sont non nulles, a.equals(b) compare leurs contenus.
Points clés
- Chaque clé unique est associée à une valeur ; les valeurs peuvent se répéter.
putremplace une valeur existante et renvoie la valeur précédente.- Un
getpour une clé absente renvoienull; son unboxing provoque uneNullPointerException. getOrDefaultne fournit une valeur par défaut que pour une clé absente.- Fais correspondre les clés textuelles de façon cohérente et compare le contenu des valeurs enveloppées.
1.2 Parcours les clés, les valeurs et les entrées
Une Map peut répondre à une recherche ponctuelle ou fournir toutes ses données à une boucle. Choisis la vue qui donne les éléments nécessaires à la boucle. Les vues sont liées à la Map : les modifications effectuées par leur intermédiaire peuvent donc aussi modifier la Map.
Choisir les clés, les valeurs ou les entrées
Utilise keySet() pour parcourir les clés. Une recherche dans cette boucle permet de retrouver chaque valeur :
for (String name : phoneBook.keySet()) {
System.out.println(name + ": " + phoneBook.get(name));
}
Utilise values() lorsque les clés n’ont pas d’importance. Pour les quantités en stock apple 15, pear 7 et fig 3 :
int total = 0;
for (int quantity : stock.values()) {
total += quantity;
}
La somme devient 25. Les valeurs répétées contribuent chacune séparément : une vue des valeurs n’est pas un ensemble.
Une entrée réunit une clé et sa valeur. Importe java.util.Map et utilise Map.Entry<K, V> avec getKey() et getValue(). Cela évite une seconde recherche :
String best = null;
int bestScore = Integer.MIN_VALUE;
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
if (best == null || entry.getValue() > bestScore) {
best = entry.getKey();
bestScore = entry.getValue();
}
}
Pour Ana 82, Ben 91 et Cai 77, le résultat est Ben avec 91. Le test best == null traite aussi le cas où le premier score est égal au plus petit int possible. Si la Map est vide, best reste à null.
Choisir explicitement l’ordre
Une HashMap ne garantit aucun ordre de parcours. Tu ne peux pas supposer qu’il s’agit de l’ordre d’insertion, de l’ordre trié ou de l’ordre affiché aujourd’hui. Une LinkedHashMap conserve l’ordre d’insertion ; une TreeMap parcourt les clés triées. Si deux scores sont égaux, la boucle précédente conserve le premier rencontré. Avec une HashMap, l’un ou l’autre des noms à égalité peut gagner. Ajoute une règle explicite de départage lorsque le résultat doit être prévisible.
Supprimer des entrées avec l’itérateur
Appeler stock.remove(key) dans une boucle for-each sur stock.keySet() modifie les clés que parcourt la boucle. Cela peut provoquer une ConcurrentModificationException. La détection n’est pas garantie : une exécution sans exception ne rend pas ce schéma valide.
Utilise la méthode de suppression propre à l’itérateur :
Iterator<Map.Entry<String, Integer>> it =
stock.entrySet().iterator();
while (it.hasNext()) {
if (it.next().getValue() == 0) {
it.remove();
}
}
Importe java.util.Iterator. Pour apple 15, pear 0, fig 0 et kiwi 4, ce code supprime pear et fig. Une autre approche sûre consiste à noter les clés dans une liste, à terminer la boucle, puis à supprimer ces clés.
Remplacer une valeur existante n’ajoute ni ne supprime de clé. Pendant un parcours des entrées, entry.setValue(entry.getValue() * 2) peut doubler les quantités sans erreur. N’ajoute pas de nouvelles clés par l’intermédiaire de la Map pendant cette boucle.
Distinguer une vue d’une copie
stock.keySet().remove("apple") supprime l’entrée correspondante de la Map. Une liste distincte créée avec new ArrayList<>(stock.keySet()) est une copie des clés présentes à cet instant. Trier cette liste ne réordonne pas la Map, et supprimer un nom de la liste ne supprime pas son association.
Points clés
- Utilise
keySet,valuesouentrySetselon les besoins de la boucle. HashMapne garantit aucun ordre de parcours ; départage explicitement les égalités.- Utilise la méthode
removed’un itérateur pour supprimer pendant le parcours. - Remplacer une valeur existante est autorisé pendant le parcours.
- Les vues sont liées à la Map ; une liste de clés copiée en est distincte.
1.3 Utilise tes propres objets comme clés de Map
Un identifiant de produit stocké sous forme de String possède déjà des règles d’égalité adaptées. Pour une clé issue de ta propre classe, tu dois décider si deux objets distincts ayant les mêmes données représentent la même clé.
Les codes de hachage ciblent la recherche ; l’égalité la confirme
Une HashMap utilise hashCode() pour aider à localiser une clé et equals() pour vérifier une correspondance. Des clés égales doivent avoir des codes de hachage égaux. Des clés différentes peuvent partager un code de hachage ; l’égalité permet tout de même de les distinguer. Les classes de valeurs standard comme String et Integer respectent déjà ce contrat.
Sans redéfinition, une classe hérite de Object une égalité fondée sur l’identité. Deux points créés séparément, de coordonnées 2 et 3, sont des clés différentes même si leurs champs correspondent :
labels.put(new Point(2, 3), "door");
String label = labels.get(new Point(2, 3));
Avec l’égalité par identité, label vaut null. La recherche a créé un second objet, différent de celui utilisé pour l’insertion.
Redéfinir les deux méthodes ensemble
Ici, les coordonnées d’un point définissent son contenu :
import java.util.Objects;
final class Point {
private final int x;
private final int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Point)) {
return false;
}
Point point = (Point) other;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
La vérification d’identité traite rapidement le cas du même objet. La vérification du type rejette null et les objets d’un autre type. La dernière comparaison vérifie les deux coordonnées. Objects.hash(x, y) construit le code de hachage à partir de ces mêmes champs. Avec cette classe, la recherche précédente renvoie "door".
Redéfinir uniquement equals laisse en place la méthode de hachage héritée, qui ne garantit pas des codes de hachage égaux pour des objets distincts dont les champs sont égaux. Une Map peut alors ne pas trouver une clé égale. Un code de hachage constant préserverait la correction du résultat, mais ralentirait la recherche. Générer les deux redéfinitions dans un éditeur aide à éviter d’utiliser des champs différents.
Utiliser la signature exacte de la méthode
public boolean equals(Point other) surcharge la méthode ; elle ne remplace pas equals(Object). La recherche dans une Map utilise equals(Object) : la nouvelle surcharge ne lui donne donc pas une égalité de contenu. L’annotation @Override transforme une signature incorrecte en erreur de compilation, au lieu de laisser un bogue de recherche caché.
Garder stables les éléments qui déterminent l’identité de la clé
Ne modifie pas les champs qui déterminent l’égalité ou le code de hachage d’une clé tant qu’elle est stockée. Si un point stocké passe de (2, 3) à (5, 3), la Map peut ne plus le retrouver sous l’une ou l’autre valeur, même si size() reste inchangée. Supprime-le avant de le modifier, puis réinsère-le. Déclarer les champs de la clé final, comme ci-dessus, empêche cette erreur.
Ces règles déterminent aussi l’appartenance à une HashSet. Une ArrayList utilise equals pour les recherches de contenu comme contains ; elle n’a pas besoin de codes de hachage pour cette recherche.
Points clés
- Des objets égaux doivent avoir des codes de hachage égaux ; des objets différents peuvent partager un même code.
- Redéfinis
equals(Object)ethashCode()avec les mêmes champs. @Overridedétecte une surcharge erronée deequals.- Ne modifie pas les champs utilisés pour l’égalité et le code de hachage tant qu’une clé est stockée.
2Compte, regroupe et indexe des données avec des Map
Une Map peut construire des informations utiles pendant qu’un programme lit des données : un effectif pour chaque mot, une liste pour chaque cours ou un objet pour chaque identifiant. Le choix important est ce que représente une valeur. Un nombre accumule un résultat ; une liste ou un ensemble réunit un groupe ; une référence à un objet constitue un index. Suis chaque mise à jour à partir d’une Map vide pour comprendre clairement le comportement lors des premières occurrences, des clés répétées et du partage d’objets.
2.1 Compte les occurrences et calcule les sommes par clé
Un tableau des effectifs possède une clé pour chaque élément distinct et un nombre indiquant ses occurrences. La première occurrence initialise un effectif ; chaque occurrence suivante met à jour cette même entrée.
Construire un effectif élément par élément
HashMap<String, Integer> counts = new HashMap<>();
for (String word : text.split(" ")) {
int oldCount = counts.getOrDefault(word, 0);
counts.put(word, oldCount + 1);
}
Pour le texte « the cat saw the dog and the cat ran », le premier "the" est absent : son ancien effectif est donc de 0 et son nouvel effectif de 1. Ses deux apparitions suivantes font passer cette entrée à 2 puis à 3. "cat" termine à 2 ; "saw", "dog", "and" et "ran" terminent chacun à 1.
Il y a 6 mots distincts, donc counts.size() vaut 6. La somme des valeurs est de 9, le nombre d’occurrences de mots. Ces nombres mesurent des choses différentes : la taille de la Map n’est pas la longueur de la séquence d’origine.
La mise à jour peut s’écrire sur une ligne :
counts.put(word, counts.getOrDefault(word, 0) + 1);
Une forme équivalente plus longue vérifie avec containsKey, incrémente un effectif existant et stocke 1 pour une nouvelle clé. Dans ce schéma, tous les effectifs stockés sont non nuls.
Préserver le résultat précédent
Appeler counts.put(word, 1) pour chaque mot remplace à chaque fois l’effectif par 1. Cela enregistre l’existence d’un mot, mais perd son effectif. Appeler counts.get(word) + 1 sans traiter la première occurrence essaie d’effectuer l’unboxing de null et échoue. La valeur par défaut intervient à l’étape de lecture ; l’effectif augmenté doit ensuite être stocké.
Décider ce qui constitue un même élément
L’égalité des chaînes est exacte. "The" et "the" sont des clés différentes, tout comme "cat" et "cat,". Si la tâche les considère comme un même mot, nettoie chaque jeton avant de le compter. Mets le texte en minuscules et supprime la ponctuation que le programme traite comme séparateur. Utilise une règle cohérente pour que les résultats ne dépendent pas de la graphie rencontrée en premier.
La clé peut aussi être un caractère. Avec HashMap<Character, Integer>, une boucle sur "banana".toCharArray() produit a=3, n=2 et b=1 avec le même schéma de lecture, d’augmentation et de stockage.
Accumuler des montants plutôt que des occurrences
Pour les sommes par catégorie, ajoute le montant actuel au lieu de 1 :
HashMap<String, Double> totals = new HashMap<>();
double oldTotal = totals.getOrDefault(category, 0.0);
totals.put(category, oldTotal + amount);
Alimentation 12,50, transport 3,20 et alimentation 7,25 donnent alimentation 19,75 et transport 3,20. La valeur par défaut est 0.0, ce qui correspond au type de valeur Double. La Map conserve une entrée par catégorie, quel que soit le nombre de montants additionnés.
Lire le tableau terminé
Parcours les entrées pour trouver le plus grand effectif ou la plus grande somme, en mémorisant la meilleure clé et sa valeur. Précise une règle de départage si nécessaire. Pour un compte rendu alphabétique, new TreeMap<>(counts) copie les associations en triant les clés. Les effectifs restent inchangés ; trier les clés ne trie pas les catégories selon leurs sommes.
Points clés
- Une Map d’effectifs stocke un effectif par clé distincte.
- Lis l’ancien effectif avec zéro comme valeur par défaut, ajoute un et stocke le résultat.
- La taille de la Map compte les éléments distincts ; la somme des effectifs mesure les occurrences.
- Normalise le texte de façon cohérente avant de compter.
- Utilise le même schéma de mise à jour pour additionner des montants par clé.
- Choisis l’ordre du compte rendu indépendamment des valeurs accumulées.
2.2 Regroupe des valeurs sous une même clé en utilisant des listes et des ensembles comme valeurs
La valeur d’une Map peut être une collection. Lorsque plusieurs étudiants suivent un même cours, le cours est une clé et la liste associée contient tous ses étudiants. La règle d’unicité des clés de la Map s’applique toujours : la liste est l’unique valeur associée à ce cours.
Créer un groupe avant d’y ajouter un élément
HashMap<Character, ArrayList<String>> groups = new HashMap<>();
for (String fruit : fruits) {
char letter = fruit.charAt(0);
if (!groups.containsKey(letter)) {
groups.put(letter, new ArrayList<>());
}
groups.get(letter).add(fruit);
}
Pour « apple », « banana », « avocado », « cherry » et « blueberry », le premier fruit crée la liste pour a et y ajoute « apple ». « Banana » crée la liste pour b. « Avocado » trouve la liste a existante et s’y ajoute. Le résultat est a → [apple, avocado], b → [banana, blueberry] et c → [cherry]. Chaque liste conserve son propre ordre d’insertion, même si la HashMap n’ordonne pas ses clés.
La vérification peut être raccourcie :
groups.putIfAbsent(letter, new ArrayList<>());
groups.get(letter).add(fruit);
putIfAbsent conserve une liste existante non nulle. Le get suivant renvoie cette liste, prête pour l’ajout.
Conserver la liste déjà construite
Un groups.put(letter, new ArrayList<>()) inconditionnel dans la boucle remplace l’ancienne liste à chaque occurrence. Seul le dernier fruit de chaque lettre subsiste après le add suivant. L’erreur inverse consiste à sauter entièrement la création : groups.get(letter).add(fruit) lève une NullPointerException pour une nouvelle clé car aucune liste n’existe encore.
Comprendre la référence
get renvoie la référence à la liste stockée. Lui ajouter un élément modifie cette même liste : il n’est donc pas nécessaire de la réinsérer. Cela explique aussi un bogue lié au partage :
ArrayList<String> shared = new ArrayList<>();
courses.put("Art", shared);
courses.put("Music", shared);
courses.get("Art").add("Jin");
Les deux clés mènent maintenant à [Jin]. Les deux clés n’ont pas créé deux listes. Crée une nouvelle liste pour chaque nouveau groupe lorsque les groupes doivent être indépendants.
Choisir des listes ou des ensembles dans les groupes
Une liste conserve les ajouts répétés. Un ensemble empêche les doublons dans ce groupe. Une HashMap<String, HashSet<String>> peut donc réunir les étudiants distincts inscrits à chaque cours sans compter deux fois le même étudiant dans un cours. La règle de l’ensemble s’applique à l’intérieur de chaque valeur ; la Map externe conserve une entrée par cours.
Pour lire un groupe qui peut être absent, vérifie avec containsKey ou utilise groups.getOrDefault(letter, new ArrayList<>()). Une clé absente donne alors une liste vide pour cet appel. La liste par défaut n’est pas automatiquement insérée ; lui ajouter un élément ne crée pas de groupe stocké.
Supprimer le dernier élément d’un groupe laisse la clé associée à une collection vide. Si le programme ne doit plus énumérer les groupes vides, vérifie avec isEmpty() et supprime aussi cette clé. Compte les groupes avec la taille de la Map externe et les éléments avec les tailles des collections internes.
Points clés
- Assure-toi qu’un groupe existe, puis ajoute un élément à sa liste ou à son ensemble stocké.
- Crée une nouvelle collection pour chaque groupe indépendant.
getrenvoie la référence stockée : les modifications internes ne nécessitent donc pas deputsupplémentaire.- Les valeurs de type liste conservent les répétitions ; celles de type ensemble conservent les éléments distincts du groupe.
- Un groupe vide stocké conserve une entrée dans la Map.
2.3 Recherche rapidement des objets et des prix avec un index fondé sur une Map
Un index associe une clé d’identification à un objet. Une bibliothèque peut trouver un livre par son ISBN sans parcourir tous les livres d’une liste. Une table de correspondance utilise la même structure pour associer un code à une valeur simple, comme le prix d’un produit.
Choisir une clé d’identification
Une HashMap<String, Book> peut associer un ISBN à son livre. Chaque recherche ne nécessite que la clé. Le nom d’une personne est souvent une mauvaise clé unique : stocker une autre personne appelée « Sam Lee » sous cette même chaîne remplace la personne précédente. Utilise un identifiant unique ou une Map de regroupement si un nom doit mener à plusieurs personnes.
Conserve un index dans la classe responsable des données :
class Library {
private HashMap<String, Book> byIsbn;
Library() {
byIsbn = new HashMap<>();
}
void addBook(Book book) {
byIsbn.put(book.getIsbn(), book);
}
Book findByIsbn(String isbn) {
return byIsbn.get(isbn);
}
}
Ici, Book fournit une méthode getIsbn(). Les appelants utilisent addBook et findByIsbn ; ils n’ont pas besoin de connaître l’implémentation de la Map stockée. Le champ privé donne aussi à la classe un endroit unique où faire respecter ses règles d’ajout et de remplacement des livres.
Vérifier un résultat absent
Si findByIsbn renvoie null, aucun livre n’a été trouvé. Teste le résultat avant d’appeler une méthode sur celui-ci :
Book found = library.findByIsbn("978-0-00-000000-2");
if (found != null) {
found.setOnLoan(true);
}
Appeler setOnLoan directement sur un résultat absent lèverait une NullPointerException. Une méthode comme hasBook(isbn) permet aussi aux appelants de vérifier la présence d’une clé.
Suivre les objets partagés entre les index
Une Map stocke une référence à un objet, pas une nouvelle copie de cet objet. Si le même livre figure dans une liste de tous les livres, une Map par ISBN et un regroupement par auteur, setOnLoan(true) modifie l’unique livre auquel les trois structures font référence. Cela évite que trois objets livre distincts divergent.
Les structures de collection elles-mêmes doivent tout de même être mises à jour. Supprimer un livre de la Map par ISBN ne supprime pas sa référence de la liste d’un auteur. Si une bibliothèque conserve les deux index, ses méthodes d’ajout et de suppression doivent mettre à jour les deux. Centraliser ces modifications dans des méthodes comme addBook et removeBook aide à garder des recherches cohérentes.
Utiliser une table dans un calcul
Supposons qu’une table de prix indique café 2,50, thé 2,00 et muffin 3,25. Pour deux cafés et un muffin :
double cost = 2 * prices.get("coffee") + prices.get("muffin");
Le sous-total des cafés est de 5,00 ; ajouter 3,25 donne 8,25. Les clés identifient les produits et les valeurs fournissent les montants. Un produit absent exige une décision explicite avant le calcul : une valeur par défaut de zéro le traiterait comme gratuit sans le signaler. La même technique de recherche peut donc nécessiter une règle différente de celle d’un tableau des effectifs pour les clés absentes.
Points clés
- Un index trouve des objets à l’aide d’une clé d’identification.
- Utilise une clé unique ou regroupe explicitement plusieurs objets correspondants.
- Les index partagent des références aux objets, mais les ajouts et les suppressions doivent mettre à jour chaque index.
- Garde les Map de données privées et expose des méthodes qui font respecter leurs règles.
3Conserve des valeurs distinctes avec des ensembles
Parfois, la question est simplement de savoir si une valeur est déjà apparue. Les ensembles répondent directement à cette question et peuvent aussi comparer des groupes de valeurs, comme les personnes participant à deux événements. L’absence de doublons change à la fois le code que tu écris et la signification de la taille finale. Commence par l’appartenance, puis combine des ensembles et choisis si leurs valeurs doivent apparaître dans l’ordre d’insertion ou dans un ordre trié.
3.1 Stocke des valeurs distinctes et teste l’appartenance avec HashSet
Un ensemble contient chaque valeur au plus une fois. Il convient aux questions comme « Cette valeur est-elle déjà apparue ? » ou « Combien de valeurs différentes sont présentes ? ». Une HashSet permet de vérifier rapidement l’appartenance en moyenne, sans garantir d’ordre d’affichage.
Ajouter et vérifier des valeurs
import java.util.HashSet;
HashSet<String> visited = new HashSet<>();
boolean first = visited.add("Oslo");
boolean second = visited.add("Lima");
boolean third = visited.add("Oslo");
visited.add("Pune");
Les trois booléens stockés sont true, true et false. Le second « Oslo » correspond à un élément existant et n’est donc pas ajouté. La taille de l’ensemble est de 3. L’ajout d’un doublon ne remplace pas une case numérotée, car un ensemble n’a pas d’indice.
visited.contains("Lima") renvoie true. visited.remove("Lima") le supprime et renvoie true ; répéter cette suppression renvoie false. Utilise une boucle for-each pour parcourir les valeurs. Il n’existe pas de get(0) pour obtenir la première valeur d’une HashSet.
Supprimer les doublons d’une liste
ArrayList<Integer> values = new ArrayList<>();
values.add(3);
values.add(1);
values.add(3);
values.add(2);
values.add(1);
HashSet<Integer> distinct = new HashSet<>(values);
L’ensemble contient trois valeurs : {1, 2, 3}. Son ordre de parcours réel n’est pas spécifié. La liste source contient toujours cinq éléments car le constructeur crée une collection distincte.
Utilise new LinkedHashSet<>(values) pour conserver l’ordre des premières occurrences, ce qui donne 3, 1, 2. Utilise new TreeSet<>(values) pour obtenir les valeurs triées, 1, 2, 3. Les ensembles sont écrits ici entre accolades pour souligner l’appartenance ; la méthode toString() standard des ensembles en Java utilise des crochets.
Détecter la première répétition
Le résultat de add peut effectuer ensemble le test d’appartenance et l’insertion :
HashSet<Integer> seen = new HashSet<>();
for (int number : numbers) {
if (!seen.add(number)) {
System.out.println(number);
break;
}
}
Pour [4, 7, 2, 7, 4], la boucle affiche 7. C’est la première valeur rencontrée une seconde fois, même si 4 est apparu plus tôt dans la séquence. Avant que 7 se répète, l’ensemble contient 4, 7 et 2. L’échec de l’insertion déclenche l’arrêt.
Savoir ce qu’un ensemble ne peut pas indiquer
Vérifier avec contains avant chaque add est inutile car add traite déjà les doublons. Une liste accompagnée d’une vérification avec contains peut aussi conserver des valeurs distinctes, mais chaque recherche dans la liste peut parcourir tous les éléments stockés. Une HashSet exprime directement la règle.
L’égalité compte pour tes propres objets. Une HashSet<Point> a besoin d’une méthode equals fondée sur le contenu et d’un hashCode cohérent pour réunir des points créés séparément avec les mêmes coordonnées. Sans ces redéfinitions, des instances distinctes restent des éléments distincts.
Enfin, size() mesure les valeurs distinctes, pas les occurrences. Les neuf mots de « the cat saw the dog and the cat ran » produisent six mots distincts. Un ensemble ne permet plus de savoir que « the » est apparu trois fois ; utilise une Map d’effectifs lorsque ces effectifs comptent.
Points clés
HashSetstocke des valeurs distinctes sans indice ni ordre garanti.addrenvoie false lorsqu’une valeur égale est déjà présente.- Un ensemble copié supprime les doublons sans modifier la liste source.
- Utilise le résultat de
addpour détecter une valeur répétée. - La taille d’un ensemble compte les valeurs distinctes ; les effectifs nécessitent une Map.
3.2 Combine des ensembles et préserve leur ordre
Les ensembles peuvent décrire des groupes et comparer leur appartenance. Si deux listes de participants à des événements contiennent plusieurs fois la même personne, un ensemble réduit d’abord chaque liste aux personnes présentes. Les opérations ensemblistes répondent ensuite aux questions portant sur l’un ou l’autre événement, les deux ou un seul.
Combiner deux groupes
Soit lundi {Ana, Ben, Cai, Dee} et mardi {Ben, Dee, Eva}.
| Question | Méthode sur une copie de lundi | Résultat |
|---|---|---|
| Qui a participé à au moins l’une des deux journées ? | addAll(tuesday) | {Ana, Ben, Cai, Dee, Eva} |
| Qui a participé aux deux journées ? | retainAll(tuesday) | {Ben, Dee} |
| Qui a participé uniquement le lundi ? | removeAll(tuesday) | {Ana, Cai} |
Ces opérations sont l’union, l’intersection et la différence. Elles modifient l’ensemble receveur et renvoient un booléen indiquant s’il a changé. Elles ne renvoient pas un nouvel ensemble de résultats.
Préserver l’original
Fais une copie avant de modifier l’appartenance si tu as encore besoin de lundi :
HashSet<String> both = new HashSet<>(monday);
both.retainAll(tuesday);
both commence avec les quatre noms du lundi. retainAll supprime Ana et Cai car elles ne figurent pas dans mardi. Lundi lui-même reste inchangé. Pour trouver les personnes présentes uniquement le mardi, commence par une copie de mardi et supprime les noms du lundi : tu obtiens {Eva}. La différence a un sens ; l’inverser change la question.
Vérifier les sous-ensembles et l’égalité
monday.containsAll(group) vérifie si toutes les valeurs de group sont présentes dans lundi. Pour {Ben, Dee}, la méthode renvoie true : ce groupe est un sous-ensemble de lundi. Elle n’exige pas que lundi contienne uniquement ces deux personnes.
Deux ensembles sont égaux lorsque leurs éléments correspondent, quels que soient leur ordre d’insertion ou leur implémentation. Une HashSet contenant « x » et « y » est égale à une TreeSet contenant « y » et « x ». L’appartenance détermine l’égalité des ensembles : l’ordre seul ne peut donc pas les rendre différents.
Choisir un ordre de parcours
| Implémentation | Ordre de parcours des éléments |
|---|---|
HashSet | Aucune garantie |
LinkedHashSet | Ordre d’insertion |
TreeSet | Ordre trié |
Les trois évitent les doublons. Utilise LinkedHashSet lorsque la première apparition de chaque nom compte. Utilise TreeSet lorsque chaque parcours doit déjà être trié. Pour les chaînes, le tri naturel suit les codes de caractères : les formes minuscules et majuscules ne se comportent pas comme dans un alphabet unique insensible à la casse.
Une TreeSet créée avec son constructeur par défaut nécessite des éléments possédant une comparaison naturelle, comme des chaînes, des nombres ou des objets qui implémentent Comparable. Dans cet ensemble, un résultat de comparaison égal à zéro indique un doublon. Une classe qui ne fournit aucune comparaison naturelle provoque une ClassCastException lors de l’insertion. Fournir un comparateur explicite est une autre façon de définir l’ordre d’une collection arborescente ; les exemples avec les réglages par défaut utilisent l’ordre naturel.
Points clés
addAll,retainAlletremoveAllmodifient l’ensemble receveur.- Copie d’abord un ensemble si tu as encore besoin de ses éléments d’origine.
containsAllvérifie un sous-ensemble ; l’égalité des ensembles ne tient pas compte de l’ordre.- Choisis une implémentation fondée sur le hachage, chaînée ou arborescente selon que tu souhaites un ordre non spécifié, l’ordre d’insertion ou un ordre trié.
4Programme avec les interfaces List, Set et Map
Le type à gauche d’une déclaration de collection indique au reste du programme les opérations qu’il peut utiliser. La classe à droite fournit ces opérations et peut garantir un ordre particulier. Apprendre à lire les deux côtés rend le code utilisant des collections plus facile à modifier et les méthodes plus faciles à réutiliser. Cela aide aussi à comprendre pourquoi une liste, un ensemble et une Map se comportent différemment même lorsqu’ils contiennent des données d’apparence similaire.
4.1 Déclare des variables et des paramètres de type interface
Une interface décrit les opérations fournies par une classe qui l’implémente. Elle permet au type d’une variable d’indiquer ce dont le code a besoin tout en laissant le choix du stockage à une classe concrète. List, Set et Map sont des interfaces liées aux collections dans java.util.
Lire les deux côtés d’une déclaration
List<String> names = new ArrayList<>();
Set<String> tags = new HashSet<>();
Map<String, Integer> counts = new HashMap<>();
Le côté gauche déclare le type de la variable. Le côté droit crée un objet d’une classe qui implémente ce type. Importe les deux types, par exemple java.util.List et java.util.ArrayList. Tu ne peux pas écrire new List<>() ou new Map<>() : une interface n’est pas un objet concret à construire.
Le code qui utilise counts peut appeler put, get et entrySet car Map les déclare. Si des clés classées par ordre alphabétique deviennent utiles, remplace la construction par new TreeMap<>(). Les appels existants se compilent toujours. Leur ordre peut changer car les implémentations peuvent garantir des ordres différents ; l’interface ne rend pas tous leurs comportements identiques.
Accepter la capacité nécessaire à une méthode
Une méthode qui ne fait que compter les mots longs peut accepter une Collection :
static int countLong(Collection<String> words, int min) {
int count = 0;
for (String word : words) {
if (word.length() >= min) {
count++;
}
}
return count;
}
Pour [« a », « tree », « house »] et un minimum de 4, elle renvoie 2. La même méthode peut recevoir une ArrayList, une LinkedList, une HashSet ou List.of(...) car elle ne fait que lire les éléments. Un ensemble peut avoir déjà supprimé des doublons et fournir ainsi des données d’entrée différentes de celles d’une liste.
Utiliser un paramètre de type interface évite d’imposer une classe de stockage particulière lorsque la méthode n’en a pas besoin. Si les positions sont nécessaires, accepte List. Si la recherche par clé est nécessaire, accepte Map.
Connaître les limites du type déclaré
List<String> names = new ArrayList<>();
names.ensureCapacity(100); // does not compile
L’objet est une ArrayList, mais List ne déclare pas ensureCapacity. Le compilateur vérifie le type déclaré de la variable. Utilise un type de classe concrète lorsque son opération particulière est réellement nécessaire ; ne modifie pas les paramètres de liste ordinaires simplement pour les faire correspondre à la classe d’un appelant.
Situer Map par rapport à Collection
List et Set étendent Collection, qui décrit un groupe d’éléments. Cette interface déclare des méthodes comme add, remove, contains, size, isEmpty, addAll et clear. La prise en charge d’une modification dépend de la collection effective.
Map n’étend pas Collection. Elle stocke des associations et fournit des vues qui sont des collections : keySet() est un Set, values() est une Collection et entrySet() est un Set d’entrées. Transmets counts.values() à une méthode qui attend une collection de valeurs, pas counts elle-même.
Une classe peut implémenter plusieurs interfaces. LinkedList implémente à la fois List et Deque, une interface de file à double extrémité. Ta propre classe indique les interfaces qu’elle s’engage à implémenter après implements, comme dans class Member implements Comparable<Member>.
Points clés
- Déclare l’interface nécessaire à gauche et construis une classe qui l’implémente à droite.
- Les paramètres de type interface acceptent différentes implémentations qui fournissent les opérations nécessaires.
- Une variable n’expose que les méthodes déclarées par son type.
ListetSetétendentCollection;Mapfournit des vues qui sont des collections.
4.2 Identifie les garanties de List, Set et Map
Choisis une interface selon les règles dont tes données ont besoin. Des contenus d’apparence similaire ne rendent pas une liste, un ensemble et une Map interchangeables : chacun donne un sens différent aux positions, aux répétitions et à l’égalité.
Comparer les garanties
| Interface | Contenu stocké | Règle importante |
|---|---|---|
List | Éléments à des positions numérotées à partir de 0 | Les éléments répétés sont autorisés |
Set | Éléments distincts | Aucune opération get par indice |
Map | Paires clé–valeur | Les clés sont uniques ; les valeurs peuvent se répéter |
ArrayList et LinkedList implémentent List. HashSet, LinkedHashSet et TreeSet implémentent Set. HashMap, LinkedHashMap et TreeMap implémentent Map. Les versions fondées sur le hachage ne garantissent aucun ordre de parcours ; les versions chaînées conservent l’ordre d’insertion ; les versions arborescentes maintiennent les éléments ou les clés triés. Réinsérer une clé existante dans une LinkedHashMap ordinaire qui suit l’ordre d’insertion conserve sa place.
Examiner la suppression dans une liste d’entiers
Une List<Integer> possède deux surcharges pertinentes :
List<Integer> numbers = new ArrayList<>(List.of(1, 5, 7));
numbers.remove(1);
L’argument 1 est un int, donc Java supprime l’élément d’indice 1 : la valeur 5. Le résultat est [1, 7]. En repartant de [1, 5, 7], numbers.remove(Integer.valueOf(1)) sélectionne la suppression par valeur et laisse [5, 7]. L’objet enveloppe désigne clairement la surcharge voulue.
Comparer les contenus avec la bonne règle
Deux listes sont égales lorsque les mêmes éléments apparaissent dans le même ordre. Une ArrayList [1, 2] est égale à une LinkedList [1, 2], mais pas à une liste [2, 1]. Deux ensembles comparent l’appartenance, sans tenir compte de l’ordre. Deux Map comparent les associations : l’ordre d’insertion ne modifie donc pas leur égalité. Leurs classes concrètes peuvent différer alors que leurs contenus sont égaux selon la règle de l’interface.
Reconnaître les collections non modifiables
List<String> labels = List.of("a", "b");
Set<Integer> levels = Set.of(1, 2, 3);
Map<String, Double> prices = Map.of("tea", 2.0, "coffee", 2.5);
Ces fabriques renvoient des collections non modifiables. Toute tentative d’ajouter, de supprimer, de remplacer ou de trier leur contenu lève UnsupportedOperationException. Map.of accepte jusqu’à dix paires clé–valeur.
Les trois rejettent les éléments, clés ou valeurs null en levant NullPointerException. Set.of rejette les éléments en double et Map.of rejette les clés en double en levant IllegalArgumentException. List.of autorise les doublons car une liste peut répéter un élément. L’ordre de parcours des ensembles et des Map issus de ces fabriques n’est pas spécifié.
Copier lorsqu’une modification est nécessaire
new ArrayList<>(labels) crée une liste modifiable contenant les mêmes éléments. new HashSet<>(someList) et new HashMap<>(someMap) créent de même des structures de collection distinctes.
Ces copies sont superficielles : elles contiennent les mêmes références aux éléments. Supprimer un élément d’une copie laisse la structure d’origine intacte, mais modifier un objet mutable par l’une ou l’autre collection modifie l’objet partagé. Une collection non modifiable empêche les modifications de sa structure ; elle ne fige pas tous les objets qu’elle contient.
Points clés
- Les listes ont des positions et autorisent les doublons ; les ensembles contiennent des éléments distincts ; les Map ont des clés uniques.
remove(1)sur une liste d’entiers supprime l’élément d’un indice ;remove(Integer.valueOf(1))supprime une valeur.- L’égalité des listes vérifie l’ordre ; celle des ensembles et des Map vérifie le contenu sans tenir compte de l’ordre d’insertion.
- Les fabriques
ofcréent des collections non modifiables et rejettent les valeurs nulles. Set.ofrejette les éléments en double ;Map.ofrejette les clés en double.- Une copie modifiable possède une structure de collection distincte, mais partage les références aux éléments.
5Trie des collections avec Comparable
Le tri place les valeurs dans un ordre que le reste du code peut utiliser. Les nombres et les chaînes connaissent déjà leur ordre naturel ; les objets de tes propres classes ont besoin d’une règle explicite. Suis le tri d’une liste, puis écris une comparaison qui traite sans erreur les nombres, le texte et les égalités. Cette règle compte aussi en dehors des listes : un ensemble ou une Map triés l’utilisent pour déterminer quand deux éléments ou clés occupent la même place.
5.1 Trie des listes de nombres et de chaînes
Une liste conserve un ordre, mais celui-ci peut simplement refléter l’arrivée des valeurs. Le tri réorganise la liste selon une règle de comparaison. Java fournit déjà un ordre naturel pour les nombres et les chaînes.
Trier une liste modifiable en place
List<Double> values = new ArrayList<>(List.of(3.5, -1.0, 2.25));
Collections.sort(values);
Importe java.util.Collections. La même liste contient maintenant [-1,0 ; 2,25 ; 3,5]. Le tri renvoie void, donc values = Collections.sort(values) ne se compile pas. values.sort(null) trie aussi dans l’ordre naturel. Pour un tableau, utilise Arrays.sort(array) ; un tableau contenant 5, 2 et 8 devient 2, 5, 8.
Prévoir l’ordre des chaînes caractère par caractère
La comparaison de chaînes examine le premier caractère qui diffère. Si une chaîne est le début d’une autre, la plus courte vient en premier. Ainsi, « apple » précède « apples ».
La liste [« pear », « Banana », « apple », « 10 », « 9 »] devient après tri [« 10 », « 9 », « Banana », « apple », « pear »]. Pour ces caractères, les chiffres précèdent les lettres majuscules, qui précèdent les minuscules. « 10 » précède « 9 » car '1' précède '9' ; l’ordre des chaînes n’interprète pas les chaînes de chiffres comme des nombres entiers. Stocke les données numériques sous forme de nombres lorsqu’un ordre numérique est nécessaire.
Utiliser des ordres différents prêts à l’emploi
names.sort(String.CASE_INSENSITIVE_ORDER);
values.sort(Collections.reverseOrder());
Le premier appel classe [« pear », « Banana », « apple »] dans l’ordre [« apple », « Banana », « pear »] sans modifier la casse stockée. Le second utilise l’ordre naturel décroissant. Les nombres 4, 9 et 1 deviennent 9, 4 et 1. Ces arguments sont des comparateurs, des objets qui fournissent un autre ordre.
Collections.reverse(list) inverse simplement la séquence actuelle. La méthode produit un ordre décroissant si cette séquence était déjà triée par ordre croissant ; elle ne trie pas à elle seule une liste quelconque.
Conserver la stabilité en cas d’égalité
Le tri des listes est stable : les éléments considérés comme égaux lors de la comparaison conservent leur ordre relatif précédent. Si une comparaison fondée uniquement sur le score met deux personnes à égalité, leur ordre antérieur dans la liste reste inchangé. La stabilité préserve cet ordre d’entrée ; elle n’invente pas de critère de départage alphabétique.
Reconnaître les échecs et les méthodes pratiques
Une liste issue de List.of(...) ne peut pas être triée en place. Copie-la d’abord dans une ArrayList. Pour une classe qui n’implémente pas Comparable, Collections.sort(list) échoue à la vérification des types lors de la compilation. Appeler list.sort(null) sur de tels objets échoue à l’exécution avec une ClassCastException lorsqu’une comparaison est nécessaire.
Collections.max(collection) et Collections.min(collection) trouvent le plus grand et le plus petit élément dans l’ordre naturel sans réorganiser la collection. Elles lèvent une NoSuchElementException pour une collection vide.
Pour obtenir les clés triées d’une Map, copie map.keySet() dans une ArrayList et trie la copie, ou utilise une TreeMap. Trier une copie de la liste des clés laisse inchangé l’ordre de parcours propre à la Map.
Points clés
Collections.sortmodifie une liste modifiable en place et renvoievoid.- L’ordre naturel des chaînes compare les caractères, pas les valeurs numériques écrites en texte.
- Utilise des comparateurs prêts à l’emploi pour obtenir l’ordre inverse ou ignorer la casse.
- Un tri stable préserve l’ordre relatif antérieur des éléments à égalité.
- Copie une liste non modifiable avant de la trier.
minetmaxtrouvent les extrema sans trier.
5.2 Implémente Comparable dans ta propre classe
Java ne peut pas deviner si un membre doit être classé selon son nom, sa taille ou un autre champ. Implémente Comparable pour donner à la classe un ordre naturel. Le code de tri peut alors demander à chaque objet de se comparer à un autre objet de cette classe.
Écrire la méthode de comparaison
class Member implements Comparable<Member> {
private String name;
private int height;
Member(String name, int height) {
this.name = name;
this.height = height;
}
@Override
public int compareTo(Member other) {
return Integer.compare(this.height, other.height);
}
}
La taille est mesurée en centimètres. Comparable<Member> précise que l’autre objet est un Member ; aucun transtypage n’est nécessaire. public int compareTo(Member other) est la méthode requise. L’interface standard Comparable se trouve dans java.lang : aucune importation n’est donc nécessaire pour l’utiliser.
Pour a.compareTo(b), un résultat négatif place a avant b, zéro les place au même rang dans la comparaison et un résultat positif place a après b. Seul le signe compte : -35 est un résultat négatif aussi valide que -1.
Suivre l’ordre
Avec la comparaison des tailles, Ana 172, Ben 165 et Cai 180 sont triés en Ben 165, Ana 172 et Cai 180. Pour placer les membres les plus grands en premier, inverse les arguments :
return Integer.compare(other.height, this.height);
Modifie la règle délibérément. Inverser les arguments inverse le sens de l’ordre pour ce champ ; cela ne change pas la signification de la taille ni les données d’un membre.
Comparer des valeurs numériques entières sans erreur
La soustraction semble pratique, mais elle peut renvoyer le mauvais signe lorsqu’un int dépasse sa capacité. Pour -2 000 000 000 et 2 000 000 000, soustraire le second du premier produit par dépassement 294 967 296, un résultat positif. Integer.compare renvoie correctement un résultat négatif.
Pour les champs décimaux, utilise Double.compare(this.price, other.price). Transtyper une différence en int fait perdre de l’information : (int) (1.8 - 1.5) vaut 0, donc des prix différents deviennent égaux dans la comparaison. Une méthode de comparaison préserve l’ordre sans tronquer la différence.
Comparer du texte et réutiliser la règle
Pour ordonner par nom, renvoie this.name.compareTo(other.name). Cette méthode suit l’ordre des caractères des chaînes. compareToIgnoreCase fournit une comparaison textuelle insensible à la casse lorsque c’est la règle souhaitée pour le champ.
Une fois qu’une classe définit un ordre naturel, des opérations comme Collections.sort, Collections.max et les comparaisons par défaut de TreeSet ou de TreeMap peuvent l’utiliser. Une classe peut aussi implémenter d’autres interfaces, séparées par des virgules après implements.
La classe possède un seul ordre naturel : un compareTo différent n’est pas choisi pour chaque liste. Utilise des objets comparateurs distincts lorsqu’un contexte exige un ordre par nom et un autre un ordre par taille. Une comparaison fondée uniquement sur la taille met aussi à égalité toutes les tailles égales ; décider si cette égalité est acceptable devient particulièrement important dans les ensembles triés.
Points clés
- Implémente
Comparable<YourClass>avec une méthodecompareTopublique. - Un résultat négatif, nul ou positif signifie respectivement avant, à égalité ou après.
- Utilise
Integer.compareetDouble.comparepour ordonner les nombres sans erreur. - Inverse les arguments de comparaison pour inverser le sens de l’ordre d’un champ.
- Une classe possède un seul ordre naturel ; les comparateurs fournissent d’autres ordres.
5.3 Départage les égalités et utilise des ensembles et des Map triés
Une comparaison principale laisse souvent des égalités. Deux films peuvent avoir la même année ou deux joueurs le même score. Un critère de départage ne fait intervenir le champ suivant que lorsque les champs précédents sont égaux dans la comparaison.
Comparer les champs par ordre de priorité
@Override
public int compareTo(Film other) {
int byYear = Integer.compare(this.year, other.year);
if (byYear != 0) {
return byYear;
}
return this.title.compareTo(other.title);
}
L’année est le critère principal. Le titre ne compte que si les années sont égales. Up (2009), Avatar (2009) et Alien (1979) sont triés en Alien (1979), Avatar (2009), Up (2009). Comparer d’abord les titres leur donnerait la priorité sur l’année et répondrait à une autre tâche de tri.
Le sens de l’ordre peut différer selon le champ. Pour les points du plus élevé au plus faible et les noms de A à Z, commence par Integer.compare(other.points, this.points). Si le résultat est zéro, renvoie this.name.compareTo(other.name). Inverser toute la liste finale inverserait aussi les noms parmi les scores à égalité.
Comprendre la règle des doublons d’un ensemble trié
Une TreeSet<Member> utilisée avec ses réglages par défaut emploie la comparaison naturelle à la fois pour ordonner les éléments et pour déterminer si un élément est déjà présent. Si Member.compareTo n’utilise que la taille, la comparaison d’Ana 172 et de Dee 172 donne zéro. Ajouter Ana renvoie true ; ajouter Dee renvoie false. Ana reste l’élément stocké, même si equals considère les deux membres comme différents.
Une liste peut conserver les deux objets à égalité ; un ensemble arborescent leur donne un seul rang dans la comparaison. Ajoute le critère de départage nécessaire s’ils doivent être distincts dans l’ensemble.
Rendre la comparaison cohérente avec l’égalité
Un ordre est cohérent avec equals lorsque la comparaison renvoie zéro si et seulement si equals renvoie true. Pour une classe dont l’égalité utilise la taille et le nom, comparer la taille puis le nom peut respecter cette règle. Si l’égalité repose sur une autre identité, comme un identifiant de membre, ajouter uniquement le nom comme critère de départage ne garantit pas cette cohérence.
La comparaison doit aussi se comporter comme un ordre valide. Si a précède b, la comparaison inverse doit placer b après a. Si a précède b et b précède c, a doit précéder c. Utiliser des méthodes qui comparent les champs dans leur intégralité selon un ordre de priorité fixe aide à respecter ces règles. Une méthode incohérente peut produire un ordre incorrect ou provoquer une IllegalArgumentException lors du tri.
Garder aussi les clés d’une Map triées
Une TreeMap trie les clés, pas les valeurs. Pour les effectifs des mots de « the cat saw the dog and the cat ran », la première clé est « and » et la dernière est « the ». firstKey() et lastKey() fournissent ces clés extrêmes. Déclare une TreeMap ou une interface de Map triée appropriée pour appeler des méthodes qu’une simple Map ne déclare pas.
La comparaison des clés définit aussi les clés correspondantes. Une seconde clé dont la comparaison donne zéro met à jour l’association existante, même si equals distingue les objets. Les collections arborescentes utilisées avec leurs réglages par défaut exigent des éléments ou des clés naturellement comparables ; insérer un objet sans comparaison adaptée lève ClassCastException. Un comparateur fourni explicitement peut définir un autre ordre.
Points clés
- Compare d’abord le champ principal et ne consulte les champs suivants qu’en cas d’égalité.
- Inverse uniquement les champs qui doivent suivre un ordre décroissant.
- Les collections arborescentes traitent un résultat de comparaison nul comme le même élément ou la même clé.
- La cohérence avec
equalsexige que la comparaison donne zéro exactement lorsque l’égalité est vraie. TreeMaptrie les clés ; ses méthodes de recherche des extrémités renvoient les clés extrêmes.- Une comparaison doit inverser les signes de façon cohérente et préserver l’ordre entre trois éléments.
6Choisis la collection adaptée à une tâche
Le choix d’une collection commence par les questions auxquelles le programme doit répondre : par position, par appartenance ou par une clé distincte. L’ordre et les doublons précisent encore ce choix. Une fois les données adaptées à la tâche, compare comment les opérations fréquentes évoluent lorsque le nombre de valeurs augmente. Une petite modification, comme créer un ensemble avant une boucle, peut supprimer des recherches répétées sans rendre le programme plus difficile à lire.
6.1 Compare le coût des opérations courantes sur les collections
Le coût d’une opération décrit comment le travail qu’elle demande augmente avec le nombre d’éléments stockés. Il aide à repérer un code rapide pour un petit exemple, mais lent lorsque la collection devient grande.
Comparer la croissance, pas les secondes
Un temps constant, O(1), reste approximativement indépendant de la taille de la collection. Un temps linéaire, O(n), peut augmenter proportionnellement au nombre d’éléments. Un temps logarithmique, O(log n), augmente lentement lorsque la taille grandit. Ces termes décrivent la croissance, pas les temps d’exécution exacts sur un ordinateur particulier.
| Collection | Opération | Coût |
|---|---|---|
ArrayList | get(i), set(i, x) | Constant |
ArrayList | Ajout en fin de liste | Constant en moyenne |
ArrayList | contains, indexOf, suppression par valeur | Linéaire |
ArrayList | Insertion ou suppression près du début | Linéaire |
HashMap / HashSet | Recherche par clé ou test d’appartenance, insertion, suppression | Constant en moyenne si les codes de hachage sont bien répartis |
TreeMap / TreeSet | Recherche, insertion, suppression | Logarithmique |
LinkedList | Ajout ou suppression à l’une ou l’autre extrémité | Constant |
LinkedList | get(i) en général | Linéaire |
Une recherche dans une ArrayList peut vérifier chaque élément ; les modifications près du début décalent les éléments suivants. Une LinkedList doit parcourir la liste jusqu’à une position : des accès répétés par indice peuvent donc être coûteux. ArrayList est un choix par défaut utile pour les opérations ordinaires sur les listes.
Repérer les parcours répétés
Supposons qu’un programme vérifie 10 000 noms dans une liste contenant 100 000 noms. Appeler list.contains(name) pour chaque nom peut nécessiter jusqu’à 1 000 000 000 vérifications d’égalité. Un appel de méthode qui semble rapide reste une recherche complète lorsqu’il est utilisé ainsi.
Construis une fois un ensemble pour les tests d’appartenance :
Set<String> allowed = new HashSet<>(allowedNames);
int matches = 0;
for (String name : incomingNames) {
if (allowed.contains(name)) {
matches++;
}
}
La construction de l’ensemble de 100 000 éléments demande du travail, puis viennent 10 000 tests d’appartenance en temps constant en moyenne. En comptant les deux étapes, le travail total augmente approximativement avec la somme des tailles des deux entrées, plutôt qu’avec leur produit. Reconstruire l’ensemble dans la boucle répéterait le travail de mise en place et supprimerait cet avantage.
Bien comprendre les garanties en moyenne
Les opérations fondées sur le hachage reposent sur des clés dont les codes de hachage répartissent bien les valeurs. Renvoyer un seul code de hachage constant pour chaque objet peut toujours respecter la règle d’égalité, mais ralentit la recherche. Ce n’est pas une solution gratuite pour éviter d’écrire une méthode de hachage utile.
Les collections arborescentes maintiennent un ordre trié avec des opérations de base en temps logarithmique. Doubler le nombre d’éléments n’ajoute qu’une petite quantité de travail de recherche. Pour 100 000 éléments, le logarithme en base deux est d’environ 16,6 ; cela indique l’ordre de grandeur de la recherche, sans garantir exactement 17 comparaisons pour chaque recherche dans un arbre Java.
Tenir compte de toute la tâche
Construire un ensemble supplémentaire coûte du temps et de la mémoire. Pour quelques éléments ou une seule recherche, la liste d’origine peut suffire. Pour des tests d’appartenance répétés, un ensemble réutilisable supprime souvent le coût principal. Pars du comportement nécessaire, puis examine les opérations répétées le plus souvent.
Points clés
- Les termes de croissance décrivent l’évolution du coût, pas un nombre de secondes mesuré.
ArrayListoffre un accès rapide par indice, mais les recherches et les modifications près du début sont linéaires.- Les recherches par hachage sont en temps constant en moyenne avec des codes de hachage adaptés ; les recherches dans un arbre sont logarithmiques.
- Construis une fois un ensemble pour remplacer les parcours répétés d’une liste lors des tests d’appartenance.
- Inclus le temps de mise en place et la mémoire dans la comparaison de solutions complètes.
6.2 Choisis une collection qui répond aux besoins de la tâche
La bonne collection conserve les informations nécessaires au programme et facilite l’expression de ses principales questions. Définis les règles des données avant de choisir le nom d’une classe familière.
Déterminer ce qui identifie un élément
| Besoin principal | Choix de départ | Exemple |
|---|---|---|
| Trouver une valeur par une clé distincte | Map | Code produit associé à un prix |
| Tester l’appartenance sans doublons | Set | Noms d’utilisateur déjà pris |
| Conserver des positions, un ordre ou des éléments répétés | List | Liste de lecture qui répète des morceaux |
| Conserver un nombre fixe de cases | Tableau | Douze mesures mensuelles de précipitations |
Un double[12] peut contenir les précipitations en millimètres lorsque le mois de chaque case est connu. Une Map dont les seules clés sont les positions 0, 1, 2 et ainsi de suite ajoute une couche qu’une liste ou un tableau fournit déjà.
Choisir l’ordre nécessaire
Pour les Map et les ensembles, utilise HashMap ou HashSet si aucun ordre n’est nécessaire, LinkedHashMap ou LinkedHashSet pour l’ordre d’insertion, et TreeMap ou TreeSet pour des clés ou éléments triés. Pour une liste polyvalente, commence par ArrayList.
Les effectifs de mots affichés par ordre alphabétique conviennent à une TreeMap<String, Integer>. Une LinkedHashSet<String> convient à une liste de mots-clés distincts dans l’ordre de leur première apparition. Les morceaux répétés nécessitent une liste, même s’ils sont aussi stockés ailleurs dans un ensemble : supprimer les répétitions changerait la liste de lecture.
Combiner les collections lorsque les données ont plusieurs niveaux
Les étudiants par cours peuvent être représentés par une Map<String, List<String>> ; chaque valeur est une liste ordonnée d’inscriptions. Les mots-clés par article peuvent être représentés par une Map<String, Set<String>> ; chaque article reçoit des mots-clés distincts. Un classement peut être une List<Player> triée selon la comparaison naturelle des joueurs.
Les choix externe et interne répondent à des questions différentes. Si les cours doivent être énumérés par ordre alphabétique et les étudiants conservés dans l’ordre d’inscription, utilise une TreeMap à l’extérieur et une liste à l’intérieur. Trier les clés ne trie pas les listes. Si les inscriptions en double doivent être ignorées, utilise plutôt un ensemble pour les groupes internes.
Garder ensemble les données liées
Deux listes parallèles, l’une pour les noms et l’autre pour les numéros de téléphone, reposent sur la correspondance des positions. Supprimer un nom sans son numéro rompt toutes les associations suivantes. Si les noms identifient les personnes de façon unique, une Map peut conserver l’association. Si les noms se répètent ou si plusieurs champs concernent une personne, conserve des objets représentant les personnes dans une liste ou indexe-les par un identifiant unique.
Rechercher sans cesse dans une liste selon un champ est un autre signe qu’il faut envisager un index fondé sur une Map. Conserve aussi la liste si l’ordre d’affichage et les entrées répétées comptent, mais maintiens les deux structures ensemble lors des ajouts ou des suppressions de données.
Vérifier les règles des éléments et le type déclaré
Utilise une déclaration avec un type interface comme Map<String, Double> prices = new HashMap<>(); pour que les appelants s’appuient sur les opérations de Map dont ils ont besoin. Les collections fondées sur le hachage nécessitent une égalité adaptée et des codes de hachage cohérents pour les clés ou éléments personnalisés. Les collections arborescentes utilisées avec leurs réglages par défaut nécessitent une comparaison naturelle qui distingue exactement les valeurs que la collection doit conserver. Ces règles permettent à la collection choisie de représenter les données voulues.
Points clés
- Choisis les Map pour la recherche par clé, les ensembles pour l’appartenance et les listes pour les positions ou les répétitions.
- Les tableaux peuvent contenir un nombre fixe de cases, y compris pour des valeurs primitives.
- Choisis délibérément entre l’ordre d’insertion et un ordre trié.
- Les collections imbriquées permettent aux clés externes et aux groupes internes de suivre des règles différentes.
- Garde les champs liés ensemble et maintiens plusieurs index à l’aide de méthodes communes.
- Adapte les règles d’égalité et de comparaison aux valeurs que la collection doit conserver.
HashMap et collections en Java : exemples
1Suis une Map de stocks, du stockage à la recherche
13 étapes
- 1IntroductionPars d’une question sur un produit
Un programme de gestion des stocks doit répondre à la question « Combien de dossiers sont disponibles ? ». Une Map fait du nom du produit la clé et de sa quantité la valeur. Suis une Map pendant un remplacement, une recherche infructueuse et un nettoyage. Examine ensuite pourquoi une clé personnalisée peut ne pas être trouvée même lorsque ses champs semblent corrects. Chaque recherche dépend de ce que Java considère comme une même clé.
- 2ExplicationCrée une association par clé
Crée
HashMap<String, Integer> stock = new HashMap<>();.Stringdécrit les clés ;Integerdécrit les valeurs. La Map utilise des types référence, doncintne peut pas être l’argument de type des valeurs. Java effectue l’autoboxing d’un littéral comme6lorsquestock.put("folder", 6)le stocke. Le diamant à droite permet à Java de déduire les deux types. - 3ExempleRemplace une quantité
Exécute ces mises à jour dans l’ordre :
stock.put("folder", 6); stock.put("clip", 11); Integer old = stock.put("folder", 8);Le dernier appel trouve la clé folder existante, stocke
8et renvoie6dansold. Il y a toujours deux clés. Une Map enregistre la dernière valeur d’une clé ; elle n’additionne pas automatiquement les quantités et n’en conserve pas l’historique. - 4DéfiLis sans insérer
Quelles sont les valeurs de
net destock.size()après cette lecture ? La Map contient toujours folder 8 et clip 11.int n = stock.getOrDefault("tape", 0);---reveal---
nvaut0et la taille reste2. La valeur par défaut est un résultat pour une clé absente, pas une entrée insérée. Une lecture avecget("tape")renvoie à la place null, dont l’unboxing enintest impossible. - 5ExplicationLis les deux éléments des paires ensemble
Une boucle sur les entrées fournit chaque clé et sa valeur ensemble :
for (Map.Entry<String, Integer> e : stock.entrySet()) { System.out.println(e.getKey() + ": " + e.getValue()); }Importe
java.util.Map. La boucle peut afficher les deux associations sans appel distinct àget. Si seule une somme est nécessaire, parcoursstock.values()et additionne les quantités ; les quantités répétées contribuent chacune séparément. - 6Point cléNe déduis pas quelle entrée vient en premier
La sortie peut afficher folder avant clip ou clip avant folder. HashMap ne garantit aucun de ces ordres. Un résultat comme une somme n’est pas affecté, mais une règle qui conserve le premier score à égalité peut dépendre du parcours. Choisis
LinkedHashMappour l’ordre d’insertion ouTreeMappour des clés triées, et prévois une règle explicite pour départager les maxima à égalité lorsque le gagnant doit être prévisible. - 7ExempleSupprime pendant le parcours
Supposons que folder vaille maintenant 0 et clip 11. Supprime les quantités nulles avec un itérateur :
Iterator<Map.Entry<String, Integer>> it = stock.entrySet().iterator(); while (it.hasNext()) { if (it.next().getValue() == 0) { it.remove(); } }L’itérateur supprime son entrée courante et poursuit le parcours sans erreur. Appeler
stock.removependant un parcours for-each peut au contraire déclencherConcurrentModificationException. - 8DéfiCrée une copie distincte des clés
Avant le nettoyage,
keysest créée avecnew ArrayList<>(stock.keySet()). Sikeys.remove("folder")est appelé, qu’arrive-t-il à la Map de stocks ?---reveal---
La Map conserve son association pour folder.
keysest une liste distincte des clés qui existaient au moment de la copie. Une suppression directement dansstock.keySet()supprimerait l’entrée de la Map, car cet objet est une vue liée. - 9ExempleEssaie une clé personnalisée
Imagine que
Binpossède les champsrowetcolumnet ne redéfinit pas les méthodes d’égalité. Stocke un libellé avecnew Bin(3, 4), puis recherche-le avec un autrenew Bin(3, 4). La recherche renvoie null. Ce sont deux objets différents et la méthodeObject.equalshéritée utilise l’identité. Les valeurs identiques des champs n’ont pas encore été intégrées à une règle de correspondance des clés. - 10ExplicationRends l’égalité et le hachage cohérents
Pour définir l’identité d’un casier selon ses coordonnées, redéfinis
equals(Object other)afin de comparer la ligne et la colonne, et redéfinishashCode()avec les mêmes champs, par exempleObjects.hash(row, column). Des coordonnées égales doivent produire des codes de hachage égaux. Un code de hachage identique ne suffit pas à établir l’égalité ; la vérification d’égalité distingue toujours des clés de coordonnées différentes. - 11DéfiRepère une surcharge
Une classe définit
public boolean equals(Bin other)et unhashCode()fondé sur ses coordonnées. Pourquoi une recherche avec un casier distinct mais d’apparence égale peut-elle encore échouer ?---reveal---
Le paramètre doit être de type
Objectpour redéfinir la méthode d’égalité de Java. La méthode dont le paramètre est de type Bin est une surcharge et laisse en place l’égalité par identité héritée. Ajouter@Overrideà cette signature incorrecte permet au compilateur de révéler l’erreur. - 12DéfiCorrige une conception qui modifie une clé
Une clé représentant un casier utilise la ligne et la colonne dans ses méthodes d’égalité et de hachage. Le programme modifie sa ligne pendant qu’elle est stockée, puis ne retrouve plus son libellé. Comment doit-il mettre à jour l’emplacement, puis supprimer sans erreur les libellés vides pendant le parcours ?
---reveal---
Supprime l’association avant de modifier la clé, puis réinsère-la. Pour le nettoyage pendant le parcours, utilise la méthode de suppression propre à l’itérateur des entrées. La stabilité de l’identité de la clé et la sûreté du parcours résolvent deux aspects différents de cette mise à jour.
- 13RécapitulatifGarde une liste de vérification pour les mises à jour de Map
Pour une recherche infructueuse, décide si une valeur par défaut ou une vérification explicite de l’absence convient à la tâche. Pour une boucle, détermine si l’ordre compte et si des clés seront supprimées. Pour une clé personnalisée, vérifie la signature exacte de
equals(Object), la concordance des champs utilisés pour le hachage et la stabilité de l’identité. Ces vérifications repèrent différentes causes d’un même symptôme : une association que le programme ne peut pas utiliser comme prévu.
2Construis les informations de présence à l’arrivée des enregistrements
12 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionTransforme les arrivées en réponses utiles
- 2ExempleCommence à compter les séances
- 3ExempleDistingue les séances distinctes des enregistrements
- 4DéfiCorrige un effectif remis à zéro
- 5ExplicationCrée un groupe une seule fois
- 6ExempleSuis la référence interne
- 7DéfiTrouve le bogue du groupe partagé
- 8ExplicationIndexe par une clé d’identification
- 9Point cléModifie un objet présent à plusieurs endroits
- 10DéfiMaintiens la cohérence lors d’une suppression
- 11DéfiCombine les effectifs et l’appartenance sans doublons
- 12RécapitulatifVérifie une première arrivée et une répétition
3Compare deux groupes de participants
9 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionCherche qui est venu, pas le nombre de passages
- 2ExempleRéunis les pointages répétés
- 3DéfiArrête-toi à la première arrivée répétée
- 4ExempleNe conserve que les membres communs
- 5ExplicationChoisis le sens de la différence
- 6DéfiTeste un groupe sélectionné
- 7ConseilChoisis un ordre utile pour le compte rendu
- 8DéfiProduis un compte rendu trié des absences
- 9RécapitulatifConsidère l’ensemble receveur comme le groupe de départ
4Lis les déclarations et les copies de collections
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionLis les deux côtés de la déclaration
- 2ExplicationDéclare ce dont l’appelant a besoin
- 3ExempleUtilise un paramètre plus général pour la lecture
- 4DéfiDiagnostique la méthode absente
- 5LienChoisis le sens du contenu
- 6ExempleSuis une suppression d’entier
- 7DéfiCopie avant de trier
- 8Point cléDistingue les modifications des objets de celles de la liste
- 9DéfiTransmets la bonne vue de la Map
- 10RécapitulatifVérifie le type, l’opération et l’objet
5Construis un classement qui traite correctement les égalités
15 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionChoisis ce qui vient en premier
- 2ExempleTrie la même liste
- 3ExplicationExamine le premier caractère différent
- 4DéfiUtilise un ordre fourni
- 5ExplicationDonne un ordre naturel à une classe
- 6ExempleÉvite une fausse égalité numérique
- 7DéfiInverse l’ordre du champ numérique
- 8ExempleNe départage que les égalités réelles
- 9ExempleSuis le classement
- 10DéfiObserve ce que conserve un ensemble arborescent
- 11Point cléFais correspondre l’ordre à l’identité
- 12LienVérifie la clé d’une Map triée
- 13DéfiConserve tous les résultats dans une liste classée
- 14ConseilFais fonctionner la règle pour trois éléments
- 15RécapitulatifVérifie une comparaison dans deux situations
6Choisis des structures pour une liste de cours
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionÉnumère les questions que pose le programme
- 2ExempleRepère le parcours dans la boucle
- 3ExplicationPrépare une seule fois les tests d’appartenance
- 4DéfiCompare des entrées qui grandissent
- 5ExempleConserve les enregistrements d’inscription répétés
- 6ExplicationChoisis l’ordre externe et l’ordre interne
- 7DéfiCorrige une règle de doublons inadaptée
- 8ConseilTiens compte du coût de l’ordre nécessaire
- 9DéfiCombine les éléments de la conception finale
- 10RécapitulatifChoisis le comportement avant de mesurer la vitesse
HashMap et collections en Java : QCM
Série 1 : Lis et mets à jour des Map de façon fiable10 Questions Pratiques
Question 1 sur 10
HashMap<String, Integer> vide reçoit put("brush", 5) puis put("brush", 14). Quelle est sa taille et quelle est la valeur associée à "brush" ?Afficher la réponseMasquer la réponse
put n’ajoute pas la quantité reçue à la quantité précédente. Une accumulation nécessite une expression qui lit puis met à jour la valeur.Question 2 sur 10
"tray". Que se passe-t-il à l’exécution de int n = map.get("tray"); ?Afficher la réponseMasquer la réponse
get pour une clé absente renvoie null et l’affectation de ce résultat à un int tente d’en effectuer l’unboxing. Null n’a pas de valeur entière primitive, donc Java lève NullPointerException. La Map ne fournit pas zéro et ne crée pas de quantité simplement parce que la variable de destination est numérique.Question 3 sur 10
Afficher la réponseMasquer la réponse
entrySet() fournit une entrée contenant à la fois une clé et sa valeur associée. Une boucle sur les clés peut retrouver la valeur par une autre recherche, mais l’élément de l’ensemble des clés ne fournit que la clé. La vue des valeurs ne permet pas d’identifier la clé associée à chaque état.Question 4 sur 10
equals correcte. Que doivent valoir leurs codes de hachage ?Afficher la réponseMasquer la réponse
Question 5 sur 10
"beam" → 9. Le programme exécute Integer old = map.put("beam", 13); puis Integer removed = map.remove("beam");. Que valent old, removed et la taille finale ?Afficher la réponseMasquer la réponse
put avec celle qu’il stocke.Question 6 sur 10
entrySet() et doit supprimer chaque entrée de valeur nulle. Comment doit-elle supprimer l’entrée pendant le parcours ?Afficher la réponseMasquer la réponse
ConcurrentModificationException. Remplacer une quantité par null ne supprimerait pas l’entrée.Question 7 sur 10
Cell définit equals(Cell other) et un hashCode fondé sur ses champs. Des cellules distinctes dont les champs sont égaux ne correspondent pas comme clés de HashMap. Quelle modification de méthode corrige l’erreur d’égalité ?Afficher la réponseMasquer la réponse
equals(Object) : la méthode dont le paramètre est de type Cell est donc une surcharge et laisse en place l’égalité par identité héritée. Redéfinis la méthode dont le paramètre est de type Object et utilise des champs correspondants pour le hachage. Modifier uniquement le code de hachage ne peut pas faire intervenir la mauvaise méthode d’égalité dans la recherche.Question 8 sur 10
Afficher la réponseMasquer la réponse
Question 9 sur 10
"ink" → 4 et "paper" → 0. keys est une nouvelle ArrayList copiée à partir de son ensemble de clés. Le programme supprime "ink" de keys, supprime "paper" par la vue de l’ensemble des clés de la Map, puis double toutes les valeurs restantes de la Map. Que reste-t-il dans la Map ?Afficher la réponseMasquer la réponse
Question 10 sur 10
Location utilisent une coordonnée mutable. Une clé est stockée, puis sa coordonnée est modifiée pendant son stockage ; la recherche ne retrouve alors plus son association. Quelle séquence de mise à jour la conception doit-elle utiliser pour éviter cet échec ?Afficher la réponseMasquer la réponse
Série 2 : Construis des effectifs et compare des groupes10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
"north" → 4, "south" → 2 et "west" → 3. Combien de clés distinctes contient-elle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
"cedar". Que renvoie un nouvel appel à add("cedar") ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
"red", "gold", "red", "blue", "gold", "red" avec counts.put(word, counts.getOrDefault(word, 0) + 1). Quels sont l’effectif de red et la taille de la Map ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
groups.put(team, new ArrayList<>()); puis groups.get(team).add(name);. Une équipe reçoit Omar, Pia, puis Ren. Que reste-t-il sous cette équipe ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
C.removeAll(B). Que contient C ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Device est stocké dans une liste et dans une Map par identifiant. Il est récupéré dans la Map, puis son champ d’état change. Quel état la référence stockée dans la liste expose-t-elle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
!seen.add(n). Quel nombre est indiqué ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
"Morning" et "Evening". Le programme ajoute "Lee" par Morning, puis remplace l’association de Evening par une nouvelle liste et ajoute "Jo" par Evening. Quels sont les groupes finaux ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
retainAll(B). D est copié à partir de B et exécute removeAll(C). Quels sont D et le résultat de A.containsAll(C) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 3 : Utilise les interfaces et trie des données10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Set<String> codes = new HashSet<>();, quel est le type déclaré de codes ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
a.compareTo(b) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
List<Integer> mutable contient initialement [4, 8, 12]. Elle exécute remove(1). Que reste-t-il ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
"zebra", "Apron", "18", "3", "ant" ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Collection<String>. Un appelant possède Map<String, String> labels et veut que la méthode traite chaque valeur de notation. Que doit-il transmettre ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
(int) (this.price - other.price). Quel problème se produit pour les prix 6,8 et 6,3 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
compareTo ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Ticket mutable. Une seconde ArrayList est copiée à partir de cette liste. Le programme modifie le libellé du ticket par la copie, puis vide celle-ci. Que contient la liste d’origine ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Reading.equals utilise l’identifiant de station et la température, mais sa comparaison naturelle n’utilise que la température. Une TreeSet utilisée avec ses réglages par défaut reçoit A à 16, B à 16, puis C à 12. Quels sont sa taille et les identifiants conservés ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 4 : Diagnostique le comportement des collections10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
"pending" explicitement associée à null. Que renvoie getOrDefault("pending", 20) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Set.of("draft", "final", "draft") ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
"Ari Chen" sont insérés et le premier ne peut plus être retrouvé par ce nom. Quelle conception conserve directement les deux pour une recherche individuelle ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
Collections.reverse(list) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
"Support". Le programme évalue List<String> result = groups.getOrDefault("Support", new ArrayList<>()); puis ajoute "Nia" à result. Que renvoie un appel ultérieur à groups.get("Support") ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
ScoreKey utilise l’équipe et les points ; sa comparaison naturelle n’utilise que les points. Une TreeMap utilisée avec ses réglages par défaut reçoit la clé East-30 avec la valeur "old", West-30 avec la valeur "new", puis North-18 avec la valeur "low". Quelle est sa taille et quelle valeur retrouve-t-on avec East-30 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
addAll(B), puis removeAll(A). Que vaut U et l’un des ensembles d’origine a-t-il changé ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 5 : Combine recherche, regroupement et ordre10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
map.values() ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
get. Quelle correction complète respecte ces exigences ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Tu bloques sur ton propre exercice ? Aide aux Devoirs
Mots-Clés
A
Appartenance
contains la teste selon la règle de correspondance de cet ensemble.Autoboxing
12 dans une Map de valeurs Integer effectue automatiquement son autoboxing pour le stockage.C
Choix d’une collection
Classe enveloppe
Integer comme type de valeur car int ne peut pas apparaître comme argument de type générique.Clé mutable
Cohérence avec equals
Collection
Collection<String> et parcourir une liste ou un ensemble.Collection imbriquée
Collection non modifiable
List.of doit être copiée avant d’être triée, mais un objet mutable stocké n’est pas figé par cette liste.Comparable
compareTo typée.Comparable<Member> pour que le tri de listes puisse ordonner ses instances par taille.Comparateur
String.CASE_INSENSITIVE_ORDER trie une liste sans modifier la casse stockée dans chaque chaîne.compareTo
Contrat de hachage
equals renvoient des codes de hachage égaux, tout en autorisant les collisions entre objets différents.x et y dans leur test d’égalité et dans leur méthode de calcul du code de hachage.Copie superficielle
Coût de mise en place
Critère de départage
D
Dépassement de capacité d’un entier
Integer.compare évite l’inversion de signe que la soustraction peut provoquer.Différence d’ensembles
É
Égalité de contenu
equals(Object).Égalité par identité
Object.Élément distinct
"sun rain sun" contient deux clés de mots distincts, mais enregistre trois occurrences.E
Encapsulation
addBook les mette à jour ensemble au lieu de laisser les appelants les modifier.Ensemble
G
getOrDefault
H
HashMap
HashMap<String, Integer> peut rechercher la quantité actuelle d’un produit sans utiliser une position dans une liste.HashSet
HashSet<String> peut suivre les noms déjà traités pendant qu’un programme lit une séquence d’entrée plus longue.I
Identifiant unique
Implémentation
HashMap et TreeMap implémentent toutes deux Map, mais garantissent des choses différentes concernant l’ordre des clés.Index
Interface
List<String> peut recevoir une ArrayList ou une LinkedList sans changer sa signature.Intersection
retainAll supprime les valeurs non partagées de son ensemble receveur.Itérateur
hasNext(), next() et le remove() de l’itérateur pour supprimer les quantités nulles.L
LinkedHashMap
LinkedHashMap qui suit l’ordre d’insertion.LinkedHashSet
LinkedHashSet perd ses répétitions tout en conservant l’ordre de première apparition des mots-clés.List
Listes parallèles
M
Map
Map.Entry
Modification structurelle
N
Normalisation des clés
O
Occurrence en double
add renvoie false.Ordre de parcours
Ordre des caractères
"7", "Bee" et "ant", l’ordre naturel des chaînes place le chiffre avant les lettres.Ordre naturel
"20" et "3" place "20" en premier car les caractères initiaux déterminent leur ordre.P
Paire clé–valeur
"pen" → 18 associe un nom de produit au nombre actuellement disponible.Paramètre de type interface
Map<String, Integer> tandis que les appelants choisissent un stockage fondé sur le hachage ou sur un arbre.putIfAbsent
putIfAbsent peut garantir que sa clé possède une liste sans remplacer une liste existante.R
Recherche par clé
Référence partagée
Regroupement
S
Somme cumulée
Sous-ensemble
a.containsAll(b) vérifie si b est inclus dans a.Surcharge
remove(1) sélectionne la suppression par indice, tandis que remove(Integer.valueOf(1)) sélectionne la suppression par valeur.Syntaxe du diamant
HashMap<String, Integer> m = new HashMap<>();, le diamant évite de répéter les deux types.T
Table de correspondance
Tableau
double[12] peut fournir à chaque mois une case pour sa mesure de précipitations en millimètres.Tableau des effectifs
Temps constant
ArrayList ne nécessite pas de parcourir toutes les positions précédentes de cette liste.Temps linéaire
Temps logarithmique
Transitivité
TreeMap
firstKey().TreeSet
Tri en place
Collections.sort(values), la variable de liste existante donne accès à ses éléments dans leur nouvel ordre.Tri stable
Troncature
Type déclaré
ArrayList stockée dans une variable List ne peut pas exposer ensureCapacity par cette variable.U
Unboxing
int le résultat d’une recherche infructueuse de valeur Integer échoue car l’unboxing du null renvoyé est impossible.Union
addAll la forme en modifiant l’ensemble receveur.V
Vue de collection
- 1Premiers programmes Java
- 2Conditions et boucles en Java
- 3Méthodes Java
- 4Listes et tableaux en Java
- 5Classes et objets en Java
- 6Références et égalité en Java
- 7HashMap et collections en Java
- 8Héritage et polymorphisme en Java
- 9Exceptions et fichiers en Java
- 10Paquetages et tests unitaires Java
- 11Généricité et flux en Java
À propos de cette unité
Crée ton propre Matériel d'Étude
Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.