2I002
CONTENEURS GÉNÉRIQUES
Vincent Guigue
Problématique générale
Construire une structure de données adaptée à différents types d’entrées
Listes : d’entier, de réels, de String...
Piles, Files, Tas...
⇒ ne pas construire une classe par cas !!!
Solution (avant Java 1.5):
1 p u b l i c c l a s s L i s t e G e n O l d {
2 p r i v a t e f i n a l s t a t i c i n t TAILLE_MAX = 5 0 0 ;
3 p r i v a t e O b j e c t [ ] l i s t e ;
4 p r i v a t e i n t s i z e ;
5
6 p u b l i c L i s t e G e n O l d ( ) {
7 l i s t e = new O b j e c t [ TAILLE_MAX ] ;
8 s i z e = 0 ;
9 }
10
11 p u b l i c v o i d add ( O b j e c t o ) { l i s t e [ s i z e ] = o ; s i z e ++;}
12 p u b l i c O b j e c t g e t (i n t i ) {r e t u r n l i s t e [ i ] ; }
13 . . . // remove , g e t S i z e . . .
14 }
2i002 – Génériques 2/14
Problématique générale
Construire une structure de données adaptée à différents types d’entrées
Listes : d’entier, de réels, de String...
Piles, Files, Tas...
⇒ ne pas construire une classe par cas !!!
Solution (avant Java 1.5):
1 p u b l i c c l a s s L i s t e G e n O l d {
2 p r i v a t e f i n a l s t a t i c i n t TAILLE_MAX = 5 0 0 ;
3 p r i v a t e O b j e c t [ ] l i s t e ;
4 p r i v a t e i n t s i z e ;
5
6 p u b l i c L i s t e G e n O l d ( ) {
7 l i s t e = new O b j e c t [ TAILLE_MAX ] ;
8 s i z e = 0 ;
9 }
10
11 p u b l i c v o i d add ( O b j e c t o ) { l i s t e [ s i z e ] = o ; s i z e ++;}
12 p u b l i c O b j e c t g e t (i n t i ) {r e t u r n l i s t e [ i ] ; }
13 . . . // remove , g e t S i z e . . .
14 }
Limites
Obligation de faire des cast à chaque récupération d’objet
Sécurisation bof : on peut mettre n’importe quoi dans la structure... + cast à la récupération
Difficilement compatible avec des algorithmes génériques (tri, min, max...)
2i002 – Génériques 3/14
Le cas ArrayList (usage)
La plupart des structures de données classiques existent déjà ArrayList, HashMap, HashSet, PriorityQueue
Usage:
ArrayList<E> = liste de E, est un type à part entière déclaration, instanciation classique
1 // s u r un e x e m p l e a v e c d e s I n t e g e r
2 A r r a y L i s t <I n t e g e r > m a L i s t e = new A r r a y L i s t <I n t e g e r > ( ) ;
get : retourne des Integer (pas besoin de cast)
on ne peut mettre que des Integer dedans
Création d’une classe générique...
Exemple (très) utile: la Paire
La plupart des langages modernes gèrent des N-uplet... Mais pas Java. On peut créer une classe Paire pour retourner facilement plusieurs valeurs depuis une méthode.
1 p u b l i c c l a s s P a i r e <A , B> {
2 p r i v a t e A e l 1 ;
3 p r i v a t e B e l 2 ;
4 p u b l i c P a i r e (A e l 1 , B e l 2 ) {
5 s u p e r( ) ;
6 t h i s. e l 1 = e l 1 ;
7 t h i s. e l 2 = e l 2 ;
8 }
9 p u b l i c A g e t E l 1 ( ) {
10 r e t u r n e l 1 ;
11 }
12 p u b l i c B g e t E l 2 ( ) {
13 r e t u r n e l 2 ;
14 }
15 }
2i002 – Génériques 5/14
Création d’une classe générique...
Exemple (très) utile: la Paire
La plupart des langages modernes gèrent des N-uplet... Mais pas Java. On peut créer une classe Paire pour retourner facilement plusieurs valeurs depuis une méthode.
1 p u b l i c c l a s s P a i r e <A , B> {
2 p r i v a t e A e l 1 ;
3 p r i v a t e B e l 2 ;
4 p u b l i c P a i r e (A e l 1 , B e l 2 ) {
5 s u p e r( ) ;
6 t h i s. e l 1 = e l 1 ;
7 t h i s. e l 2 = e l 2 ;
8 }
9 p u b l i c A g e t E l 1 ( ) {
10 r e t u r n e l 1 ;
11 }
12 p u b l i c B g e t E l 2 ( ) {
13 r e t u r n e l 2 ;
14 }
15 }
... Et usage client
La syntaxe est celle des ArrayList... Vous la connaissez déjà!
1 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
2 P a i r e <I n t e g e r , S t r i n g > p =
3 new P a i r e <I n t e g e r , S t r i n g >(2 , " t o t o ") ;
4 S y s t e m . o u t . p r i n t l n ( p . g e t E l 1 ()+" ␣ "+p . g e t E l 2 ( ) ) ;
5 }
Le type est donc: Paire<Integer, String>
Le type du contenant est passé en argument spécial entre <>
2i002 – Génériques 6/14
Extension d’une classe générique (1)
Besoin d’une liste avec des méthodes spécifiques... Mais toujours générique
exemple récupération de la case du milieu
1 p u b l i c c l a s s M a L i s t e M i l i e u <E> e x t e n d s A r r a y L i s t <E>{
2 // c o n s t r u c t e u r s a n s a r g u m e n t p a r d e f a u t
3 // L e s m e t h o d e s s o n t h e r i t e e s : add , g e t , s i z e . . .
4
5 // Methode s p e c i f i q u e
6 p u b l i c E g e t M i l i e u ( ) {
7 r e t u r n s u p e r. g e t (s u p e r. s i z e ( ) / 2 ) ; // d i v i s i o n e n t i e r e
8 }
9 10 }
Usage client:
1 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
2 M a L i s t e M i l i e u <Double> l i =
3 new M a L i s t e M i l i e u <Double > ( ) ;
4 l i . add ( 2 . 0 ) ; l i . add ( 1 . 4 ) ; l i . add ( 3 . 7 ) ;
5 S y s t e m . o u t . p r i n t l n ( l i . g e t M i l i e u ( ) ) ;
Extension d’une classe générique (2) Besoin d’une liste de quelque chose
ex. du TD: créer un aquarium = liste de Poisson Train = liste de wagon
Population = liste de personne ...
1 p u b l i c c l a s s Aquarium e x t e n d s A r r a y L i s t <P o i s s o n >{
2 // bcp de m e t h o d e s h e r i t e e s ! ! !
3 }
Usage client: la liste ne gère que des poissons
1 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
2 Aquarium aqua = new Aquarium ( ) ;
3 aqua . add (new Thon ( ) ) ;
4 aqua . add (new R e q u i n ( ) ) ;
5 . . .
6 }
2i002 – Génériques 8/14
Cast sur les objets génériques <E>
1
Coté contenu : très agréable (et classique) objets de types E et descendants de E récupération d’objets dans des variables E
2
Coté contenant : non flexible
1 A r r a y L i s t <P e r s o n n e > pop = new A r r a y L i s t <P e r s o n n e > ( ) ; // OK
2 // E t u d i a n t e x t e n d s P e r s o n n e
3 A r r a y L i s t <P e r s o n n e > promo = new A r r a y L i s t <E t u d i a n t > ( ) ; // KO
⇒ Une seule issue (en cas de besoin) : la syntaxe wildcard
La syntaxe wildcard
Subsomption contenu/contenant
On a besoin de cette propriété pour définir des algorithmes génériques.
Syntaxe : ArrayList<?> ou ArrayList<? extends Poisson>
N’importe quelle liste, ou n’importe quelle liste d’objets dérivés de poissons:
1 A r r a y L i s t <? e x t e n d s P o i s s o n > l i = new A r r a y L i s t <Thon > ( ) ;
Exemple: comment proposer une technique de recherche de minimum dans une liste sans connaitre le type de contenu?
1
Définir une propriété: Comparable
2
Définir un algorithme acceptant n’importe quelle conteneur d’objets comparables en utilisant la syntaxe wildcard
ATTENTION: ce type de syntaxe empêche toute modification sur l’objet passé
2i002 – Génériques 10/14
La syntaxe wildcard
Subsomption contenu/contenant
On a besoin de cette propriété pour définir des algorithmes génériques.
Syntaxe : ArrayList<?> ou ArrayList<? extends Poisson>
N’importe quelle liste, ou n’importe quelle liste d’objets dérivés de poissons:
1 A r r a y L i s t <? e x t e n d s P o i s s o n > l i = new A r r a y L i s t <Thon > ( ) ;
Exemple: comment proposer une technique de recherche de minimum dans une liste sans connaitre le type de contenu?
1
Définir une propriété: Comparable
2
Définir un algorithme acceptant n’importe quelle conteneur d’objets comparables en utilisant la syntaxe wildcard
ATTENTION: ce type de syntaxe empêche toute modification sur
l’objet passé
La syntaxe wildcard (préliminaires)
1
Définir une propriété: Comparable
1 p u b l i c i n t e r f a c e C o m p a r a b l e <E> {
2 // r e t o u r n e −1 s i r e f < o b j , 0 s i e g a l i t e , 1 s i n o n
3 p u b l i c i n t compareTo ( E o b j ) ;
4 }
Avec par exemple un Poisson répondant à la spécification:
1 p u b l i c c l a s s P o i s s o n impleme nts C o m p a r a b l e <P o i s s o n >{
2 p r i v a t e d o u b l e t a i l l e ;
3
4 p u b l i c P o i s s o n (d o u b l e t a i l l e ) {
5 s u p e r( ) ;
6 t h i s. t a i l l e = t a i l l e ;
7 }
8 p u b l i c d o u b l e g e t T a i l l e ( ) {
9 r e t u r n t a i l l e ;
10 }
11 p u b l i c i n t compareTo ( P o i s s o n o b j ) {
12 i f( t a i l l e <o b j . t a i l l e ) r e t u r n −1;
13 e l s e i f( t a i l l e ==o b j . t a i l l e ) r e t u r n 0 ;
14 r e t u r n 1 ;
15 }
16 }
2i002 – Génériques 11/14
La syntaxe wildcard
2
Utiliser la propriété dans un algorithme générique:
1 p u b l i c c l a s s G e n e r i c T o o l s <E e x t e n d s C o m p a r a b l e <E>> {
2
3 // c o n s t r u c t e u r p a r d e f a u t
4 p u b l i c E getMinimum ( A r r a y L i s t <? e x t e n d s E> l i s t e ) {
5 E min = l i s t e . g e t ( 0 ) ;
6 f o r (i n t i =1; i < l i s t e . s i z e ( ) ; i ++){
7 // s i : min > l i s t e . g e t ( i )
8 i f( min . compareTo ( l i s t e . g e t ( i ) ) == 1 )
9 min = l i s t e . g e t ( i ) ;
10 }
11 r e t u r n min ;
12 }
13 }
Usage coté client:
1 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
2 A r r a y L i s t <P o i s s o n > a q u a r i u m = new A r r a y L i s t <P o i s s o n > ( ) ;
3 G e n e r i c T o o l s <P o i s s o n > t o o l = new G e n e r i c T o o l s <P o i s s o n > ( ) ;
4 P o i s s o n l e P l u s P e t i t = t o o l . getMinimum ( a q u a r i u m ) ;
5 }
La syntaxe wildcard +++
Générique & static
La même chose en version static: il faut rendre une méthode paramétrique au lieu d’une classe
1 // s y n t a x e s t a t i c au n i v e a u d ’ une methode
2 p u b l i c s t a t i c <T e x t e n d s O b j e c t & C o m p a r a b l e <? s u p e r T>>
3 T g e t M i n i m u m S t a t i c ( A r r a y L i s t <? e x t e n d s T> l i s t e ) {
4 T min = l i s t e . g e t ( 0 ) ;
5 f o r (i n t i =1; i < l i s t e . s i z e ( ) ; i ++){
6 // min > l i s t e . g e t ( i )
7 i f( min . compareTo ( l i s t e . g e t ( i ) ) == 1 )
8 min = l i s t e . g e t ( i ) ;
9 }
10 r e t u r n min ;
11 }
Usage coté client:
1 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
2 A r r a y L i s t <P o i s s o n > a q u a r i u m = new A r r a y L i s t <P o i s s o n > ( ) ;
3 P o i s s o n l e P l u s P e t i t v 2 =
4 G e n e r i c T o o l s . g e t M i n i m u m S t a t i c ( a q u a r i u m ) ;
5 }
2i002 – Génériques 13/14