Les conteneurs Java ou Collections
Transcription
Les conteneurs Java ou Collections
Les conteneurs Java ou Collections Daniel Tschirhart : Programmation Java V1.34 Daniel Tschirhart : Programmation Java V1.34 Type de Donnée Abstrait (T.D.A.) Un conteneur est un Type de Donnée Abstrait (T.D.A.) (également appelé collection) destiné à contenir des objets. Il existe deux types de conteneurs : Les conteneurs séquentiels : Les vecteurs, piles, files, sacs, ensembles Les conteneurs associatifs : Les dictionnaires (map) 2 Daniel Tschirhart : Programmation Java V1.34 Conteneurs séquentiels les vecteurs (tableau), Les piles Les files Les sacs Les ensembles 3 Daniel Tschirhart : Programmation Java V1.34 Les vecteurs Dans un vecteur la donnée est directement accessible à l’aide d’un index appelé indice. Une implémentation directe d’un vecteur peut être réalisée à l’aide d’un vecteur classique, mais d’autre structures de données sont possibles. Un vecteur se prête mal pour l’ajout ou la suppression gestion des données. Tableau T indice maximal indice minimal 4 Daniel Tschirhart : Programmation Java V1.34 Les Piles Deux opérations principales sont permises : empiler (insérer à la tête ou un sommet) et dépiler (supprimer au sommet). Sommet de pile (TOS) v3 v3 v2 v2 v2 v1 v1 v1 v3 v3 v3 avant empilement après empilement et avant dépilement v3 après dépilement 5 Daniel Tschirhart : Programmation Java V1.34 Les Files fifo Une file est comme la pile, une structure de données à accès restreint. Deux opérations principales sont permises : ajouter (insérer à la queue de la file) et suivant (obtenir l’élément en tête le retirer de la file). Queue v2 Tête v6 v2 v4 v2 v6 v2 v4 v2 v6 v2 avant l'ajout de v2 dans la file après l'ajout de v2 et avant la sortie de la tête de file après la sortie de la tête de file v4 6 Daniel Tschirhart : Programmation Java V1.34 Les Sacs (bags) Un TDA de type sac est une collection de données non ordonnée. Un sac peut contenir plusieurs fois la même donnée. Un sac est utilisé pour stocker des objets, l’ordre dans le quel les objets sont stockés n’ayant aucune importance. Ajout de V4 et V2 dans un sac 7 Daniel Tschirhart : Programmation Java V1.34 Les ensembles (set) Les ensembles sont similaires aux sac, excepté qu’il ne peuvent contenir plusieurs données identiques. Ce type de collection implémente les opération sur les ensembles (union, intersection, ...). 8 Daniel Tschirhart : Programmation Java V1.34 Structures de données fondamentales Les structures de donnée fondamentales (S.D.F.) sont la représentation concrète des types de données abstrait 9 Daniel Tschirhart : Programmation Java V1.34 Structures de données utilisées utilisées dans les T.D.A. Tableau Un tableau peut être utiliser pour implémenter directement un vecteur, une pile, une file, un sac. L’accès est très rapide mais l’ajout ou la suppression des données en dehors du haut du tableau est proportionnelle à la taille du tableau. 10 Daniel Tschirhart : Programmation Java V1.34 Structures de données utilisées Tableau Un tableau peut être utiliser pour implémenter directement un vecteur, une pile, une file, un sac. L’accès est très rapide mais l’ajout ou la suppression des données en dehors du haut du tableau est proportionnelle à la taille du tableau. 11 Daniel Tschirhart : Programmation Java V1.34 Liste liée L Une liste liée est un ensemble d'éléments organisés séquentiellement et reliés par des lien explicites I S T E 12 Daniel Tschirhart : Programmation Java V1.34 Liste liée (2) La figure met en évidence les éléments suivants : Chaque nœud possède un lien, ce qui implique que le dernier nœud doit référer un nœud suivant. On convient alors d'un nœud sentinelle ou nœud factice (figure ci-dessous). Chaque nœud est repéré par un lien précédent ce qui implique que le premier nœud doit posséder un élément qui le repère. Ce nœud sera appelé entête (figure ci-dessous). De même que la fin de la liste doit spécifier un repère de fin (sentinelle). 13 Daniel Tschirhart : Programmation Java V1.34 Réorganisation d'une liste Entête L I S T E Sentinelle Entête E I S T L Sentinelle 14 Daniel Tschirhart : Programmation Java V1.34 Insertion et suppression d'un élément dans une liste liée X Entête L I S T E Sentinelle X Entête L I S T E Sentinelle 15 Daniel Tschirhart : Programmation Java V1.34 Listes doublement liées Ce type de liste permet d’atteindre avec la même efficacité, la tête de liste et la fin de liste. 16 Daniel Tschirhart : Programmation Java V1.34 Les arbres binaires Un arbre est une liste liée où chaque nœud pointe en avant sur plusieurs nœuds. La racine de l'arbre est le premier nœud. Un sous-arbre est constitué d'un nœud est de tous les nœuds en dessous de lui. Le nœud terminal (feuille) est un nœud sans descendant. Un nœud donné a un parent (le nœud au-dessus de lui) sauf si c'est la racine, peut avoir des frères (les nœuds issus d'un même parent) ou des descendants (nœuds qu'il pointe directement). Les arbres binaires sont utilisés par le conteneur TreeMap 17 Daniel Tschirhart : Programmation Java V1.34 Exemple d'arbre binaire 18 Daniel Tschirhart : Programmation Java V1.34 Tables à adressage dispersé (hastable) Les tables à adressage dispersé (table de hachages) sont utilisés dans java pour accélérer (considérablement) le recherche d’un élément dans un conteneur non trié. Exemple : sans hachage la recherche d’un élément dans un conteneur séquentiel nécessite en moyenne de parcourir taille/2 éléments (taille = nombre d’éléments dans le conteneur). 19 Daniel Tschirhart : Programmation Java V1.34 Constitution d'une table de hachage La table de hachage est constituée d’un tableau de listes chaînées Chaque emplacement de tableau est appelé seau 20 Daniel Tschirhart : Programmation Java V1.34 Fonctionnement d'une table de hachage Pour trouver la place d’un élément dans le tableau (numéro du seau) on calcule son code de hachage puis on le réduit par le modulo du nombre total de seaux. Exemple : code de hachage calculé= 345 avec 100 seaux, l’objet est placé dans le seau 45 (345:100=45) avec un peu de chance le seau sera vide, sinon (collision de hachage) il faut parcourir la liste comportant tous les éléments du seau pour déterminer si l’objet en fait partie. En utilisant des codes de hachage distribués aléatoirement et avec un nombre de seaux suffisamment grand (+50% de la taille de collection) il suffit en général d’effectuer uniquement quelques comparaisons 21 Daniel Tschirhart : Programmation Java V1.34 Le choix d'un conteneur Le choix d'un conteneur doit être adapté au problème à traiter : L'accès à un objets doit t'il être direct ou peut-il être séquentiel ? Le conteneur doit-il être triés ? L'ordre d'insertion ou d'extraction a-t-il une importance ? Doit–on insérer ou supprimer un objet au milieu d'une collection ? Un objet peut t-il être dupliqué à l'intérieur d'une collection ? 22 Daniel Tschirhart : Programmation Java V1.34 Les collections séquentielles dans Java Collection List ArrayList Vector Stack Set LinkedList SortedList HashSet TreeSet 23 Daniel Tschirhart : Programmation Java V1.34 Parcourir les collections Tous les conteneurs sauf Stack, sont parcourus de la même manière à l'aide d'un itérateur. Un iterateur est un objet permettant de faire l'abstraction de la structure de donnée fondamentale sous jacente du conteneur. Ainsi les conteneurs Vector, ArrayList, LinkedList incorporent tous un objet de type Iterator. Principales méthodes d'un itérateur Java 24 Daniel Tschirhart : Programmation Java V1.34 Exemple de parcours d'une liste à l’aide d’un itérateur List<Complex> l = new LinkedList<Complex>(); l.add(new Complex(3,5)); Iterator<Complex> it = l.iterator(); while (it.hasNext()) System.out.println(it.next()); 25 Daniel Tschirhart : Programmation Java V1.34 Boucle foreach Java 5 possède une nouvelle construction for (foreach) simplifiant le parcours d’une collection. Ici l1 est un objet de type String for (String s : l1) System.out.println(s); 26 Daniel Tschirhart : Programmation Java V1.34 Suppression d’un élément dans une collection Pour supprimer un élément du conteneur il faut l'avoir lu auparavant : it.next(); it.remove(); it.remove(); it.next(); it.remove(); it.next(); it.remove(); // faux // correct 27 Daniel Tschirhart : Programmation Java V1.34 Interface List Cette interface déclare les méthodes que doit implémenter ArrayList, Vector, LinkedList 28 Daniel Tschirhart : Programmation Java V1.34 Vector, ArrayList, LinkedList Ces conteneurs sont des tableaux dynamiques (leur taille augmente automatiquement). Ils sont bien adaptés pour manipuler les données situés à un indice quelconque sauf au début ou à la fin de la liste auquel cas il faut leur préférer la liste liée LinkedList. Toutes ces classes dérivent de l'interface List. 29 Daniel Tschirhart : Programmation Java V1.34 Classe Vector Tableau qui s'agrandi automatiquement. La classe est dite synchronisée : l'accès d'un objet de type Vector peut être effectué de façon concurrente. Exemple d'utilisation : List<Complex> l = new Vector<Complex>(); l.add(new Complex(3, 4)); 30 Daniel Tschirhart : Programmation Java V1.34 Classe ArrayList Liste implémentés à l'aide d'un tableau. La classe n'est pas synchronisée. Exemple d'utilisation : List<Complex> l = new ArrayList<Complex>(); l.add(new Complex(3, 4)); 31 Daniel Tschirhart : Programmation Java V1.34 Classe LinkedList Liste implémentés à l'aide d'une liste liée. La classe n'est pas synchronisée. Exemple d'utilisation : List<Complex> l = new LinkedList<Complex>(); l.add(new Complex(3, 4)); 32 Daniel Tschirhart : Programmation Java V1.34 Exemple complet import java.util.*; public class TestListe1 { public static void main(String[] args) { List<String> l1 = new ArrayList<String>(); l1.add("-L3-"); l1.add("-L2-"); l1.add("-L1-"); l1.add("-L0-"); // Afficher la liste System.out.println(l1); // Parcourir la liste for (Iterator<String> it = l1.iterator(); it.hasNext(); ) System.out.println(it.next()); // Trier la liste Collections.sort(l1); System.out.println(l1); // Parcourir la liste avec foreach for (String s : l1) System.out.println(s); //Supprimer le deuxième élément; Iterator<String> it = l1.iterator(); it.next(); it.next(); it.remove(); System.out.println(l1); } } 33 Daniel Tschirhart : Programmation Java V1.34 Exemple List Liste : exemple 2 34 Daniel Tschirhart : Programmation Java V1.34 Exemple List2 Liste : exemple 3 On veut insérer, dans l’exemple ci-dessus, si un élément en tête de liste. On ne peut pas le faire à l’aide de la méthode générale add de l'interface list, mais avec la méthode addFirst de la classe LinkedList Justification : addFirst n’est pas présente dans l’interface List parce que cette opération est très coûteuse pour les structures de données de type vecteur. Pour utiliser addFirst il faut créer directement un objet du type LinkedList. En affichant la liste on obtient 35 Daniel Tschirhart : Programmation Java V1.34 Exemple Vector Classe Vector : exemple 4 36 Daniel Tschirhart : Programmation Java V1.34 Classe Stack Une pile est un conteneur séquentiel. Les piles java utilisent une SDF vecteur 37 Daniel Tschirhart : Programmation Java V1.34 Ensembles HashSet, TreeSet HashSet et TreeSet implémentent l’interface Set HashSet utilise une table d’adressage dispersée, alors que TreeSet utilise un arbre binaire. L’accès aux éléments d’un ensemble ne se fait pas à l’aide d’un indice et une seule occurrence de donnée est autorisée dans l’ensemble. 38 Daniel Tschirhart : Programmation Java V1.34 Méthodes disponibles dans l’interface Set 39 Daniel Tschirhart : Programmation Java V1.34 Exemples utilisant l’interface Set 40 Daniel Tschirhart : Programmation Java V1.34 Conteneurs associatifs Les données sont organisées par paires : clé + donnée. Map<String, String> m = new TreeMap<String, String>(); m.put("Lajoie", "05 46 66 33 50"); "Lajoie" est la clé, "05 46 66 33 50" la donnée. La clé ou index sert à retrouver la donnée associée. 41 Daniel Tschirhart : Programmation Java V1.34 Hiérarchie des classes des conteneurs associatifs 42 Daniel Tschirhart : Programmation Java V1.34 Classe MAP (Interface) 43 Daniel Tschirhart : Programmation Java V1.34 Classe TreeMap Un dictionnaire TreeMap trie les clés. Exemple : annuaire téléphonique utilisant un TreeMap 44 Daniel Tschirhart : Programmation Java V1.34 Manipulation d’un TreeMap Un TreeMap ne permet pas de récupérer les clés individuellement (index). Il faut utiliser un ensemble Set On récupère une clé -> s puis on récupère la donnée associée à la clé que l'on l'utilise pour indexer le dictionnaire 45 Daniel Tschirhart : Programmation Java V1.34 Classe HashMap Ne trie pas les clés mais offre un accès 20% plus rapide que le conteneur précédent. On peut reprendre intégralement les exemples précédents en remplaçant TreeMap par HashMap 46