1. Introduction
Autrefois, nous avons déjà parlé des « tableaux infinis » — les listes. Approfondissons nos connaissances et, pour cela, reposons-nous la question : qu’est-ce qu’un tableau « classique » ? Si l’on y regarde de près, il ressemble à une boîte à outils avec un nombre fixe de compartiments. Supposons que la boîte ait 10 cases. Vous obtenez un 11e outil : que faire maintenant ? Il faut acheter une nouvelle boîte ! De même, un tableau traditionnel a une taille fixe, et après sa création, sa longueur ne change pas.
Si vous devez ajouter ou supprimer un élément, vous devez créer un nouveau tableau et copier les données manuellement. Dans un tableau, on peut facilement et rapidement trouver un élément par son index, mais insérer un élément au milieu du tableau — ce n’est pas simplement « insérer », c’est « décaler tout à droite », et lors de la suppression — « décaler tout à gauche ». C’est lent et peu pratique. En outre, un tableau ne porte aucune « logique » supplémentaire : il ne fait que conserver un ensemble de cases, et il faut réaliser le tri, la recherche par contenu ou la vérification d’unicité avec des moyens externes.
Exemple : liste dynamique d’étudiants
Supposons que vous écriviez une application pour gérer les étudiants d’un groupe. Au début, il y a 5 personnes, puis une autre arrive, puis quelqu’un part. Avec un tableau, cela ressemblerait à ceci :
String[] students = new String[5];
students[0] = "Ivan";
students[1] = "Mariya";
// et ainsi de suite...
// Oups, un étudiant de plus est arrivé
// Il faut créer un nouveau tableau !
String[] newStudents = new String[6];
for (int i = 0; i < students.length; i++) {
newStudents[i] = students[i];
}
newStudents[5] = "Aleksey";
students = newStudents;
Pratique ? Disons plutôt non. Et s’il y a beaucoup d’opérations de ce type ? Là, on veut quelque chose de plus commode…
2. Qu’est-ce qu’une collection ?
Une collection est un objet qui sert de conteneur pour stocker un groupe d’autres objets (des éléments). Les collections permettent d’ajouter, de supprimer, d’itérer sur les éléments, ainsi que d’effectuer d’autres opérations : recherche, tri, filtrage, etc.
En Java, toutes les collections implémentent ou héritent de l’interface Collection (ou, pour les associations — de Map). Une collection n’est pas juste un « amas de choses », c’est une structure qui fournit un ensemble de méthodes pratique et bien conçu pour travailler avec les éléments.
Pourquoi les collections sont-elles des objets ?
Parce que les collections sont implémentées sous forme de classes ; vous pouvez donc créer des collections de n’importe quels objets, les combiner, les hériter, les étendre, et les utiliser dans vos propres classes et méthodes.
Exemple :
import java.util.ArrayList;
import java.util.List;
List<String> students = new ArrayList<>();
students.add("Ivan");
students.add("Mariya");
students.add("Aleksey");
Et voilà ! Vous pouvez maintenant ajouter autant d’étudiants que vous le souhaitez, sans vous soucier de la taille du tableau.
3. Tâches typiques résolues par les collections
Les collections sont un couteau suisse pour travailler avec les données. Voici les tâches qu’elles permettent de résoudre :
- Stockage d’une liste de données dynamique : Par exemple, la liste des étudiants, des tâches dans un planificateur, des messages dans un chat.
- Recherche et filtrage : Trouver rapidement un élément, vérifier sa présence, obtenir tous les éléments qui satisfont un certain critère.
- Tri : Trier facilement les éléments selon le critère voulu.
- Suppression et ajout d’éléments : Insérer et supprimer des éléments à n’importe quel endroit de la collection sans avoir à copier des tableaux manuellement.
- Groupement par clé : Par exemple, un annuaire téléphonique où chaque nom correspond à un numéro.
- Garantie d’unicité : Par exemple, l’ensemble de tous les mots uniques dans un texte.
Exemple : annuaire téléphonique
Avec un tableau :
- Comment trouver le numéro par nom ? Il faut parcourir le tableau et comparer les noms.
- Comment ajouter une nouvelle paire ? Il faut agrandir le tableau.
- Comment garantir que les noms ne se répètent pas ? Encore plus compliqué.
Avec une collection :
- Utilisez une Map<String, String> — et tout est prêt à l’emploi.
4. Vue d’ensemble des principaux types de collections
En Java, les collections se divisent en trois grands groupes :
| Type de collection | Interface/Classe | Utilisation |
|---|---|---|
| Liste | List, ArrayList | Ensemble ordonné d’éléments, accepte les doublons, accès par index |
| Ensemble | Set, HashSet | Ne conserve que des éléments uniques, ordre non garanti |
| Association (Map) | Map, HashMap | Stocke des paires clé-valeur, recherche rapide par clé |
Listes (List)
- Collections ordonnées, autorisent les doublons.
- Possibilité d’obtenir un élément par index.
- Exemples : ArrayList, LinkedList.
Ensembles (Set)
- Ne conservent que des éléments uniques.
- Pas d’accès par index.
- Exemples : HashSet, TreeSet.
Associations (Map)
- Stockent des paires clé-valeur.
- Recherche rapide par clé.
- Exemples : HashMap, TreeMap.
Schéma visuel (très approximatif) :
+------------------+ +-------------------+ +---------------------+
| List | | Set | | Map |
|------------------| |-------------------| |---------------------|
| [a, b, c, d, a] | | {a, b, c, d} | | {a=1, b=2, c=3} |
| Indexation : oui | | Indexation : non | | Recherche par clé |
| Doublons : oui | | Doublons : non | | Clés uniques |
+------------------+ +-------------------+ +---------------------+
5. Points utiles
Quand utiliser quelle collection ?
List — lorsque l’ordre des éléments est important, que les doublons sont nécessaires et que l’accès par index est requis (par exemple, une liste de tâches, l’historique des messages).
Set — lorsque vous avez besoin uniquement d’éléments uniques et que l’ordre n’a pas d’importance (par exemple, l’ensemble des utilisateurs uniques).
Map — lorsque vous devez faire correspondre des clés et des valeurs (par exemple, un annuaire téléphonique, où le nom est la clé et le numéro de téléphone la valeur).
Analogies de la vie courante
List — la file d’attente à la cantine : premier arrivé — premier servi, on peut se mettre dans la file plusieurs fois (doublons).
Set — la liste des invités à une fête : chaque invité n’apparaît qu’une seule fois (unicité).
Map — un carnet d’adresses : chaque nom possède son numéro de téléphone.
Aide-mémoire rapide : collections vs tableaux
| Tableau (int[]) | Collection (List<Integer>) | |
|---|---|---|
| Taille | Fixe | Dynamique |
| Ajout d’un élément | Peu pratique | Facile : add() |
| Suppression d’un élément | Peu pratique | Facile : remove() |
| Recherche par valeur | Parcours manuel | Méthodes : contains(), etc. |
| Tri | Via Arrays.sort() | Via Collections.sort(), méthodes des collections |
| Gestion de l’unicité | Non | Via Set |
| Paires clé-valeur | Non | Via Map |
6. Lien entre les collections et la POO
Les collections sont des objets qui implémentent certaines interfaces (List, Set, Map). Cela signifie que vous pouvez :
- Stocker dans les collections n’importe quels objets, y compris des instances de vos propres classes.
- Créer des collections de collections (par exemple, une liste de listes).
- Utiliser des collections comme paramètres et valeurs de retour de méthodes.
- Étendre la fonctionnalité des collections grâce à l’héritage et à la composition.
Exemple : une collection d’objets de votre classe
import java.util.ArrayList;
import java.util.List;
class Student {
String name;
int age;
// Constructeur, getters/setters, etc.
}
public class Main {
public static void main(String[] args) {
List<Student> group = new ArrayList<>();
group.add(new Student("Ivan", 20));
group.add(new Student("Mariya", 21));
// et ainsi de suite...
}
}
7. Erreurs courantes lors de l’utilisation des collections
Erreur n° 1 : utiliser des collections sans type (raw types).
Si vous écrivez ArrayList list = new ArrayList(), alors lors de l’ajout de n’importe quel objet (par exemple, des chaînes et des nombres mélangés) le compilateur ne se plaindra pas, mais plus tard, en essayant de récupérer un élément et de le convertir vers le type voulu, vous pouvez obtenir une erreur à l’exécution (ClassCastException). Utilisez toujours les génériques : ArrayList<String> list = new ArrayList<>().
Erreur n° 2 : oublier d’importer la classe nécessaire.
Si vous voyez l’erreur « cannot find symbol », vérifiez qu’au début du fichier se trouve la ligne import java.util.ArrayList; ou l’import nécessaire pour votre collection.
Erreur n° 3 : confusion entre collections et tableaux.
Une collection n’est pas un tableau ! Une collection n’a pas de champ length ; utilisez à la place la méthode size(). Un tableau n’a pas de méthode add(), et une collection n’a pas l’opérateur [] pour l’accès par index (seulement les listes via get(index)).
Erreur n° 4 : s’attendre à ce que l’ordre des éléments soit toujours conservé.
Si vous utilisez un Set ou une Map, l’ordre des éléments n’est pas garanti (sauf si vous utilisez des implémentations spécifiques comme LinkedHashSet ou TreeMap). Pour des données ordonnées, utilisez List ou des collections appropriées.
Erreur n° 5 : utiliser des types primitifs dans les collections.
Les collections ne peuvent stocker que des objets, pas des types primitifs. Autrement dit, vous ne pouvez pas créer List<int>, seulement List<Integer>. N’oubliez pas les classes enveloppes !
GO TO FULL VERSION