Cours Java détaillé
Chapitre 9 : Set - Chapitre 10 :
Map
Explications en français avec exemples complets, résultats et analyse
ligne par ligne
Objectif : comprendre quand utiliser Set ou Map, savoir choisir HashSet, LinkedHashSet,
TreeSet, HashMap, LinkedHashMap et TreeMap, et manipuler correctement les méthodes
principales.
Cours Java - Set et Map Page 1
Plan du document
• Rappel : différence entre List, Set et Map.
• Chapitre 9 : Set - définition, méthodes, HashSet, LinkedHashSet, TreeSet, objets personnalisés.
• Chapitre 10 : Map - principe clé-valeur, méthodes, parcours, HashMap, LinkedHashMap, TreeMap.
• Exemples pratiques : suppression des doublons, comptage des occurrences, combinaison Set +
Map.
• Tableaux récapitulatifs et erreurs fréquentes à éviter.
1. Rappel : List, Set et Map
En Java, les collections servent à stocker plusieurs données. Mais chaque famille a une logique
différente. Avant de commencer Set et Map, il faut bien distinguer List, Set et Map.
Type Rôle Doublons Exemple
List Stocke des éléments dans un ordre avec Oui [Ali, Ali, Sami]
index
Set Stocke des éléments uniques Non [Ali, Sami]
Map Stocke des paires clé-valeur Clés uniques 1 -> Ahmed, 2 -> Ali
Phrase à retenir : List = ordre avec index, Set = éléments uniques, Map = association
clé-valeur.
Cours Java - Set et Map Page 2
Chapitre 9 - Set
2.1 Définition de Set
Un Set est une collection qui n'accepte pas les doublons. Cela signifie qu'un même élément ne peut
pas être présent deux fois dans le même Set.
Le Set est utile lorsqu'on veut représenter une liste d'éléments uniques : emails uniques, noms de
villes sans répétition, identifiants déjà utilisés, catégories, tags, etc.
Exemple 1 : ajouter des noms dans un HashSet
import [Link];
import [Link];
public class TestSet {
public static void main(String[] args) {
Set<String> noms = new HashSet<String>();
[Link]("Ahmed");
[Link]("Ali");
[Link]("Ahmed");
[Link]("Sami");
[Link](noms);
}
}
Résultat possible :
[Ahmed, Ali, Sami]
Même si "Ahmed" a été ajouté deux fois, il apparaît une seule fois, car un Set refuse les doublons.
Attention : avec HashSet, l'ordre d'affichage n'est pas garanti. Le résultat peut être affiché
dans un autre ordre selon l'exécution.
2.2 Méthodes importantes de Set
Les méthodes principales de Set sont proches de celles des collections classiques : add, remove,
contains, size, isEmpty et clear.
Exemple 2 : méthodes de base
import [Link];
import [Link];
public class TestSetMethods {
public static void main(String[] args) {
Set<String> villes = new HashSet<String>();
[Link]("Tunis");
[Link]("Sfax");
[Link]("Sousse");
[Link]([Link]("Sfax"));
[Link]([Link]());
[Link]("Tunis");
[Link](villes);
}
}
Résultat possible :
true
3
[Sfax, Sousse]
Méthode Rôle Exemple
add(element) Ajoute un élément s'il n'existe pas déjà [Link]("Tunis")
Cours Java - Set et Map Page 3
Méthode Rôle Exemple
contains(element) Vérifie si un élément existe [Link]("Sfax")
remove(element) Supprime un élément [Link]("Tunis")
size() Retourne le nombre d'éléments [Link]()
isEmpty() Vérifie si le Set est vide [Link]()
clear() Supprime tous les éléments [Link]()
Cours Java - Set et Map Page 4
2.3 Les trois types principaux de Set
Les implémentations les plus utilisées sont HashSet, LinkedHashSet et TreeSet.
Type Doublons Ordre Tri Quand l'utiliser ?
HashSet Non Non garanti Non Quand on veut la rapidité et que l'ordre n'est
pas important.
LinkedHashSet Non Ordre d'insertion Non Quand on veut supprimer les doublons tout en
gardant l'ordre d'ajout.
TreeSet Non Ordre trié Oui Quand on veut des éléments
automatiquement triés.
A. HashSet
HashSet est rapide, mais il ne garantit pas l'ordre des éléments.
Set<String> noms = new HashSet<String>();
[Link]("Sami");
[Link]("Ahmed");
[Link]("Ali");
[Link](noms);
Résultat possible :
[Ahmed, Ali, Sami]
L'ordre peut être différent de l'ordre d'ajout. C'est normal avec HashSet.
B. LinkedHashSet
LinkedHashSet garde l'ordre d'insertion tout en refusant les doublons.
import [Link];
import [Link];
Set<String> noms = new LinkedHashSet<String>();
[Link]("Sami");
[Link]("Ahmed");
[Link]("Ali");
[Link]("Ahmed");
[Link](noms);
Résultat :
[Sami, Ahmed, Ali]
Ahmed est ajouté une seule fois, mais l'ordre d'insertion est conservé : Sami, Ahmed, Ali.
C. TreeSet
TreeSet refuse les doublons et trie automatiquement les éléments.
import [Link];
import [Link];
Set<String> noms = new TreeSet<String>();
[Link]("Sami");
[Link]("Ahmed");
[Link]("Ali");
[Link](noms);
Résultat :
[Ahmed, Ali, Sami]
Cours Java - Set et Map Page 5
Les chaînes sont triées alphabétiquement.
Set<Integer> nombres = new TreeSet<Integer>();
[Link](5);
[Link](1);
[Link](10);
[Link](3);
[Link](nombres);
Résultat :
[1, 3, 5, 10]
Cours Java - Set et Map Page 6
2.4 HashSet avec des objets personnalisés
Avec des objets personnalisés, il faut comprendre une chose importante : deux objets peuvent avoir
les mêmes attributs, mais Java peut les considérer comme différents s'ils sont deux instances
différentes en mémoire.
Exemple 3 : problème sans equals() et hashCode()
import [Link];
import [Link];
class Etudiant {
String nom;
int age;
public Etudiant(String nom, int age) {
[Link] = nom;
[Link] = age;
}
public String toString() {
return nom + " - " + age;
}
}
public class TestEtudiantSet {
public static void main(String[] args) {
Set<Etudiant> etudiants = new HashSet<Etudiant>();
[Link](new Etudiant("Ahmed", 22));
[Link](new Etudiant("Ahmed", 22));
[Link](etudiants);
}
}
Résultat possible :
[Ahmed - 22, Ahmed - 22]
Pourquoi ? Parce que les deux objets ont les mêmes valeurs, mais ce sont deux objets créés
séparément avec new. Java ne sait pas encore que deux étudiants avec le même nom et le même
âge doivent être considérés comme égaux.
Solution : redéfinir equals() et hashCode()
HashSet utilise hashCode() pour trouver rapidement la zone de stockage, puis equals() pour vérifier
l'égalité réelle entre deux objets.
import [Link];
class Etudiant {
String nom;
int age;
public Etudiant(String nom, int age) {
[Link] = nom;
[Link] = age;
}
public String toString() {
return nom + " - " + age;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != [Link]()) {
return false;
}
Etudiant autre = (Etudiant) obj;
return age == [Link] && [Link]([Link]);
}
Cours Java - Set et Map Page 7
public int hashCode() {
return [Link](nom, age);
}
}
Maintenant, si on ajoute deux fois un étudiant avec le même nom et le même âge, HashSet garde
seulement une seule occurrence.
Règle importante : si on redéfinit equals(), il faut aussi redéfinir hashCode(). Les deux
méthodes doivent être cohérentes.
Cours Java - Set et Map Page 8
2.5 TreeSet avec des objets personnalisés
TreeSet trie les éléments. Pour trier des objets personnalisés, Java doit savoir comment comparer
deux objets. On peut utiliser Comparable ou Comparator.
Exemple 4 : TreeSet avec Comparable
import [Link];
import [Link];
class Etudiant implements Comparable<Etudiant> {
String nom;
int age;
public Etudiant(String nom, int age) {
[Link] = nom;
[Link] = age;
}
public int compareTo(Etudiant autre) {
return [Link]([Link], [Link]);
}
public String toString() {
return nom + " - " + age;
}
}
public class TestTreeSet {
public static void main(String[] args) {
Set<Etudiant> etudiants = new TreeSet<Etudiant>();
[Link](new Etudiant("Ahmed", 22));
[Link](new Etudiant("Ali", 20));
[Link](new Etudiant("Sami", 25));
[Link](etudiants);
}
}
Résultat :
[Ali - 20, Ahmed - 22, Sami - 25]
Les étudiants sont triés par âge croissant, car compareTo() compare [Link] avec [Link].
Attention : dans un TreeSet, si compareTo() retourne 0, Java considère que les deux objets
sont égaux pour le tri et garde un seul élément.
2.6 Résumé du chapitre Set
Question Réponse courte
Set accepte-t-il les doublons ? Non.
HashSet garde-t-il l'ordre ? Non, l'ordre n'est pas garanti.
LinkedHashSet garde-t-il l'ordre ? Oui, l'ordre d'insertion.
TreeSet trie-t-il les éléments ? Oui, automatiquement.
Pourquoi equals() et hashCode() ? Pour comparer correctement des objets personnalisés dans HashSet.
Pourquoi Comparable dans TreeSet ? Pour dire à Java comment trier les objets personnalisés.
Cours Java - Set et Map Page 9
Chapitre 10 - Map
3.1 Définition de Map
Une Map est une structure qui stocke des données sous forme de paires clé-valeur.
clé -> valeur
1 -> Ahmed
2 -> Ali
3 -> Sami
La clé sert à retrouver rapidement la valeur. Dans une Map, les clés sont uniques. Une même clé ne
peut pas exister deux fois.
Une Map n'hérite pas directement de Collection comme List ou Set, car elle ne stocke pas des
éléments simples, mais des associations clé-valeur.
3.2 Exemple simple avec HashMap
import [Link];
import [Link];
public class TestMap {
public static void main(String[] args) {
Map<Integer, String> etudiants = new HashMap<Integer, String>();
[Link](1, "Ahmed");
[Link](2, "Ali");
[Link](3, "Sami");
[Link](etudiants);
}
}
Résultat possible :
{1=Ahmed, 2=Ali, 3=Sami}
Ici, la clé est un Integer et la valeur est un String.
Map<Integer, String>
Cela signifie : clé de type Integer, valeur de type String.
3.3 Ajouter et récupérer une valeur
[Link](1, "Ahmed");
[Link](2, "Ali");
String nom = [Link](1);
[Link](nom);
Résultat :
Ahmed
get(1) cherche la valeur associée à la clé 1. Comme la clé 1 correspond à Ahmed, Java retourne
Ahmed.
3.4 Clé unique : remplacement de valeur
Si on utilise put() avec une clé qui existe déjà, Java ne crée pas une deuxième entrée. Il remplace
l'ancienne valeur.
Map<Integer, String> etudiants = new HashMap<Integer, String>();
[Link](1, "Ahmed");
[Link](1, "Ali");
[Link](etudiants);
Cours Java - Set et Map Page 10
Résultat :
{1=Ali}
La valeur Ahmed a été remplacée par Ali, car la clé 1 existait déjà.
Règle : même clé = remplacement de valeur ; nouvelle clé = nouvelle entrée.
Cours Java - Set et Map Page 11
3.5 Méthodes importantes de Map
Map<Integer, String> etudiants = new HashMap<Integer, String>();
[Link](1, "Ahmed");
[Link](2, "Ali");
[Link](3, "Sami");
[Link]([Link](2));
[Link]([Link](1));
[Link]([Link]("Sami"));
[Link]([Link]());
[Link](2);
[Link](etudiants);
Résultat possible :
Ali
true
true
3
{1=Ahmed, 3=Sami}
Méthode Rôle Exemple
put(key, value) Ajoute ou modifie une paire clé-valeur [Link](1, "Ahmed")
get(key) Récupère la valeur associée à une clé [Link](1)
remove(key) Supprime l'entrée qui possède cette clé [Link](1)
containsKey(key) Vérifie si une clé existe [Link](1)
containsValue(value) Vérifie si une valeur existe [Link]("Ali")
size() Retourne le nombre de paires [Link]()
isEmpty() Vérifie si la Map est vide [Link]()
3.6 Parcourir une Map
Une Map contient des clés et des valeurs. On peut donc la parcourir de trois façons : par les clés, par
les valeurs ou par les paires clé-valeur.
A. Parcourir les clés avec keySet()
for (Integer id : [Link]()) {
[Link](id);
}
Cette boucle affiche seulement les clés.
B. Parcourir les valeurs avec values()
for (String nom : [Link]()) {
[Link](nom);
}
Cette boucle affiche seulement les valeurs.
C. Parcourir clé et valeur avec entrySet()
for ([Link]<Integer, String> entry : [Link]()) {
[Link]([Link]() + " -> " + [Link]());
}
entrySet() est souvent la méthode la plus utile, car elle donne directement la clé et la valeur.
Cours Java - Set et Map Page 12
3.7 Les types principaux de Map
Type Ordre Tri Particularité
HashMap Non garanti Non Rapide et très utilisée.
LinkedHashMap Ordre d'insertion Non Garde l'ordre d'ajout.
TreeMap Selon les clés Oui Trie automatiquement par clé.
Hashtable Non garanti Non Ancienne, synchronisée, n'accepte pas
null.
A. HashMap
HashMap est l'implémentation la plus utilisée. Elle est rapide, mais ne garantit pas l'ordre.
Map<Integer, String> map = new HashMap<Integer, String>();
[Link](3, "Sami");
[Link](1, "Ahmed");
[Link](2, "Ali");
[Link](map);
Résultat possible :
{1=Ahmed, 2=Ali, 3=Sami}
L'ordre peut changer. Il ne faut pas compter sur l'ordre avec HashMap.
B. LinkedHashMap
LinkedHashMap garde l'ordre dans lequel les paires ont été ajoutées.
import [Link];
import [Link];
Map<Integer, String> map = new LinkedHashMap<Integer, String>();
[Link](3, "Sami");
[Link](1, "Ahmed");
[Link](2, "Ali");
[Link](map);
Résultat :
{3=Sami, 1=Ahmed, 2=Ali}
C. TreeMap
TreeMap trie automatiquement les entrées selon les clés.
import [Link];
import [Link];
Map<Integer, String> map = new TreeMap<Integer, String>();
[Link](3, "Sami");
[Link](1, "Ahmed");
[Link](2, "Ali");
[Link](map);
Résultat :
{1=Ahmed, 2=Ali, 3=Sami}
Même si on a ajouté 3 puis 1 puis 2, TreeMap trie selon les clés : 1, 2, 3.
Cours Java - Set et Map Page 13
3.8 Exemple pratique : compter les occurrences des mots
C'est un exemple très important pour comprendre l'utilité d'une Map. On veut compter combien de
fois chaque mot apparaît dans une phrase.
import [Link];
import [Link];
public class CompteurMots {
public static void main(String[] args) {
String texte = "java spring java angular java spring";
String[] mots = [Link](" ");
Map<String, Integer> compteur = new HashMap<String, Integer>();
for (String mot : mots) {
if ([Link](mot)) {
[Link](mot, [Link](mot) + 1);
} else {
[Link](mot, 1);
}
}
[Link](compteur);
}
}
Résultat possible :
{spring=2, java=3, angular=1}
Explication étape par étape :
Mot lu Action Map après traitement
java java n'existe pas, on ajoute java=1 {java=1}
spring spring n'existe pas, on ajoute spring=1 {java=1, spring=1}
java java existe, on ajoute 1 à sa valeur {java=2, spring=1}
angular angular n'existe pas, on ajoute angular=1 {java=2, spring=1, angular=1}
java java existe, on passe de 2 à 3 {java=3, spring=1, angular=1}
spring spring existe, on passe de 1 à 2 {java=3, spring=2, angular=1}
3.9 Version simplifiée avec getOrDefault()
La méthode getOrDefault() permet de simplifier le code de comptage.
for (String mot : mots) {
[Link](mot, [Link](mot, 0) + 1);
}
Cette ligne signifie : si le mot existe, récupérer sa valeur actuelle ; sinon utiliser 0. Ensuite, ajouter 1
et enregistrer la nouvelle valeur.
getOrDefault(cle, valeurParDefaut) est très pratique pour éviter un if-else lorsque la clé peut
ne pas exister.
Cours Java - Set et Map Page 14
3.10 Map avec objets personnalisés comme valeur
Une Map peut stocker des objets comme valeurs. Par exemple, on peut associer un identifiant à un
objet Etudiant.
import [Link];
import [Link];
class Etudiant {
String nom;
int age;
public Etudiant(String nom, int age) {
[Link] = nom;
[Link] = age;
}
public String toString() {
return nom + " - " + age;
}
}
public class TestMapObjet {
public static void main(String[] args) {
Map<Integer, Etudiant> etudiants = new HashMap<Integer, Etudiant>();
[Link](1, new Etudiant("Ahmed", 22));
[Link](2, new Etudiant("Ali", 20));
[Link]([Link](1));
}
}
Résultat :
Ahmed - 22
Ici, la clé est l'identifiant de l'étudiant et la valeur est l'objet Etudiant complet.
3.11 Exemple qui combine Set et Map
On peut utiliser Set et Map ensemble. Par exemple, à partir d'une liste de noms avec répétitions, on
veut obtenir les noms uniques et compter les occurrences.
import [Link].*;
public class SetMapExample {
public static void main(String[] args) {
List<String> noms = [Link](
"Ahmed", "Ali", "Ahmed", "Sami", "Ali", "Ahmed"
);
Set<String> nomsUniques = new HashSet<String>();
Map<String, Integer> compteur = new HashMap<String, Integer>();
for (String nom : noms) {
[Link](nom);
[Link](nom, [Link](nom, 0) + 1);
}
[Link]("Noms uniques : " + nomsUniques);
[Link]("Occurrences : " + compteur);
}
}
Résultat possible :
Noms uniques : [Ahmed, Ali, Sami]
Occurrences : {Ahmed=3, Ali=2, Sami=1}
Le Set garde chaque nom une seule fois. La Map associe chaque nom au nombre de fois où il
apparaît.
Cours Java - Set et Map Page 15
4. Comparaison finale : Set vs Map
Point Set Map
Stocke quoi ? Des éléments simples Des paires clé-valeur
Doublons Pas de doublons Pas de clés dupliquées
Méthode d'ajout add(element) put(key, value)
Méthode de lecture contains(element) get(key)
Exemple Set Map
Utilisation réelle Emails uniques, tags, catégories ID -> étudiant, mot -> occurrence
5. Erreurs fréquentes à éviter
Erreur 1 : croire que HashSet garde l'ordre
HashSet ne garantit pas l'ordre. Pour garder l'ordre d'insertion, utiliser LinkedHashSet.
Erreur 2 : oublier equals() et hashCode() avec HashSet
Si on utilise un HashSet avec des objets personnalisés, il faut souvent redéfinir equals() et hashCode()
pour éviter les faux doublons.
Erreur 3 : croire qu'une Map accepte deux fois la même clé
Une Map n'accepte pas deux fois la même clé. Si on met une nouvelle valeur avec une clé existante,
l'ancienne valeur est remplacée.
Erreur 4 : parcourir une Map comme une List
Une Map ne se parcourt pas par index. On utilise keySet(), values() ou entrySet().
Erreur 5 : utiliser TreeSet sans règle de comparaison
Pour des objets personnalisés dans TreeSet, il faut définir un ordre avec Comparable ou Comparator.
6. Résumé final à mémoriser
Set sert à garder des éléments uniques. Map sert à associer une clé unique à une valeur.
Besoin Structure conseillée
Supprimer les doublons HashSet ou LinkedHashSet
Supprimer les doublons et garder l'ordre LinkedHashSet
Avoir des éléments triés TreeSet
Associer un ID à un nom HashMap
Garder l'ordre d'ajout dans une Map LinkedHashMap
Trier automatiquement selon les clés TreeMap
Compter les occurrences HashMap
Cours Java - Set et Map Page 16