Généricité et interfaces

1 - Quelque classes de la bibliothèque standard

Nous allons commencer par découvrir quelques classes de la bibliothèque standard qui utilisent des interfaces et de la généricité. Pour votre apprentissage, vous avez eu l'occasion de programmer votre propre version de ces classes. Bien entendu, maintenant que vous avez compris leur fonctionnement, à l'avenir, vous pourrez utiliser les versions présentes dans la bibliothèque standard. Attention, par soucis pédagogique, nous ne mentionnons ici qu'une petite partie du contenu de la bibliothèque standard, n'hésitez pas à l'explorer plus avant par vous même si vous vous sentez confiants.

Commençons par le thème du moment : les listes chaînées. La bibliothèque standard abstrait l'objet représenté par une liste chaînée comme une séquence. Cette abstraction est décrite par l'interface List. Une séquence est un ensemble d'éléments de même type associés à un indice entier, leur position dans la séquence. Une telle structure de données peut être implémentée sous forme de tableau ou de liste chaînée. Java vous propose les deux : la ArrayList est une séquence stockée dans un tableau, tandis que la LinkedList est une séquence stockée sous forme de liste chaînée. Bien entendu, ces deux variantes proposent les mêmes fonctionnalités : ajout d'élément, suppression d'élément, recherche d'élément,... La principale différence sera l'efficacité de ces opérations selon l'implémentation sous jacente. Par exemple, l'accès à un élément d'indice donné sera plus efficace dans un tableau, tandis que l'insertion en tête sera plus efficace dans une liste chaînée.

Les autres structures que vous avez pu manipuler se trouvent également dans la bibliothèque standard :

Questions :

2 - Itérateurs

Dans la liste chainée que vous avez programmée, le parcours est quelque chose d'interne à votre classe. Un parcours est nécessaire lors de la recherche d'un élément par exemple. Cependant, rien ne permet à l'utilisateur de votre liste chainée de parcourir tous les éléments de votre liste pour y appliquer un traitement non prévu par votre implémentation. La seule solution est de la vider, élément par élément, et de la remplir à nouveau.

Dans la bibliothèque standard, un objet, l'itérateur, abstrait la notion de position dans une séquence et vous permet de la parcourir sans connaître le détail de son implémentation. Une position peut se trouver au tout début, avant tout élément de la séquence (position 0), entre les éléments d'indice i et i+1 (position i) ou après tous les éléments (position n pour une séquence de taille n). Vous pouvez trouver une explication de cette notion de position dans la documentation de l'interface ListIterator. L'itérateur est créé typiquement au début de la séquence et offre typiquement les opérations suivantes :

L'utilisation typique d'un itérateur ressemble à :

ListIterator<Integer> it = list.listIterator();
while (it.hasNext()) {
	Integer i = it.next();
	System.out.println(i);
}
Attention si une modification de la liste est effectuée par un autre objet (un autre itérateur par exemple) avant la fin du parcours par un itérateur, l'état interne de l'itérateur est potentiellement corrompu.

Questions :

3 - Vos propres classes génériques

Il est temps d'écrire vos propre classes génériques. Nous allons prendre l'exemple de la FAP qui va nous permettre d'illustrer toutes les notions vues aujourd'hui. Partez de votre solution à l'exercice sur les FAP abordé lors d'un précédent TP ou récupérez et comprenez la correction proposée.

Questions :