:: Enseignements :: ESIPE :: E4INFO :: 2015-2016 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | TP noté de Java Avancé |
Le TP à pour but de créer différentes implantations d'une suite d'éléments manipulables
au travers d'une interface Suite
Rappel, vous devez configurer le workspace d'eclipse (File > Switch WorkSpace) pour
qu'il corresponde au répertoire EXAM que vous avez dans le home
de votre session de TP noté.
Attention à bien lire le sujet en entier.
L'interface
fr.umlv.suite.Suite représente une suite non mutable d'élements
(comme
java.util.List). L'interface est définie par deux méthodes
-
size qui renvoie le nombre d'élements de la suite.
Toutes les implantations de size doivent être en temps constant.
-
get(index) qui renvoie l'élement à l'index index sachant
que les élements sont rangés de 0 à size - 1.
Pour toutes les implantations, si l'index n'est pas valide une exception
IndexOutOfBoundsException doit être lancée.
Toutes les implantations de
Suite ne permettent pas de stocker
null
et sont non-mutables.
Exercice 1 - Nice Suit(e)
Les implantations de l'interface
fr.umlv.suite.Suite seront regroupées
(au moins au début) dans une
garbage class nommée
fr.umlv.suite.SuiteImpls juste pour des questions de rangement.
Les tests JUnit pour toutes les questions du TP sont dans la classe
SuiteTest.java.
-
Avant propos, indiquer l'ensemble des méthodes de l'interface java.util.stream.Stream
avec pour chaque méthode une ligne écrite en francais décrivant ce que fait la méthode.
-
On veut implanter une méthode from dans l'interface fr.umlv.suite.Suite
permettant de créer des suites en séparant les différents élements par
des virgules. Par exemple,
Suite<String> suite = Suite.from("hello", "suite");
Suite<Integer> suite2 = Suite.from(1, 2, 3);
On demande à ce que l'implantation de l'interface utilisée par from
soit une classe interne nommée ElementSuite dans la classe fr.umlv.suite.SuiteImpls
et que celle-ci n'utilise pas de structure de données définies dans le package java.util.
Créer l'interface fr.umlv.suite.Suite avec les deux méthodes size et get
ainsi que la méthode from.
Attention à ce que la méthode from soit correctement paramétrée
et que le compilateur ne reporte pas de warning pour cette méthode.
-
On souhaite ajouter une méthode empty permettant de créer une suite vide, comme ceci
Suite<String> suite = Suite.empty();
Suite<Integer> suite2 = Suite.empty();
La classe implantant une suite vide doit aussi être une classe interne de fr.umlv.suite.SuiteImpls
nommée EmptySuite. Dans un but d'économiser un peu la mémoire, cette implantation
ne doit pas posséder de champs et la méthode empty doit toujours renvoyer la même instance
(un peu comme un singleton).
-
On souhaite ajouter une méthode contains à l'interface Suite qui renvoie vrai
si un élement pris en paramètre est dans la suite et faux sinon.
On peut noter qu'il n'est pas nécessaire d'implanter contains dans chaque classe
implantant l'interface Suite car il est possible d'implanter contains en utilisant
juste les méthodes size et get.
-
On souhaite ajouter une méthode forEach qui permet d'effectuer une action
(faisant un effet de bord) sur chaque élement de la suite.
Suite<String> suite = ...
suite.forEach(element -> System.out.println("element " + element));
Attention à ce que la signature de la méthode forEach soit la plus "générique" possible.
-
On souhaite ajouter une méthode span à l'interface Suite
pour permettre la création de suite à partir d'une taille et d'une fonction qui associe à un index,
l'élement correspondant dans la suite.
Par exemple,
Suite<Integer> suite = Suite.span(3, x -> x * 2);
correspond à la suite 0, 2, 4 c'est à dire, la suite de 3 élements dont l'élement 0 est 0 * 2,
l'élement 1 est 1 * 2 et l'élement 2 est 2 * 2.
Contrairement au deux premières implantations de l'interface Suite qui ont été écrites
dans la classe SuiteImpls, cette implantation devra être écrite directement dans
span sous forme d'une classe anonyme.
Enfin, cette implantation ne doit pas stocker les élements mais recalculer l'élement à chaque
fois que cela est nécessaire.
Comme pour la méthode forEach attention à ce que la signature de la méthode
soit la plus "générique" possible.
-
En fait, il est possible de ré-implanter la méthode from en utilisant la méthode span
ce qui va permettre de partager du code.
Mettre en commentaire l'ancienne méthode from ainsi que la classe ElementSuite
dans la classe SuiteImpls puis écrivez une nouvelle version de la méthode from
qui utilise la méthode span.
-
On cherche à écrire une méthode map qui fonctionne comme Stream.map, c'est à dire
qui prend une fonction en paramètre et qui renvoie une Suite dont les élements sont les élements
de la suite sur laquelle la méthode map est appelée auxquels on a appliqué la fonction
pris en paramètre.
Comme pour span, la suite retournée par la méthode map ne doit pas stocker les élements
mais les recalculer lorsque cela est nécessaire.
Comme pour les méthodes forEach et span, attention à ce que la signature de la méthode
soit la plus "générique" possible.
-
On peut remarquer que lorsque la suite est vide ; créée par empty ; alors la méthode map
doit aussi renvoyer une suite vide. Il est donc possible "d'optimiser" un peu le code pour éviter
de re-créer une suite vide.
-
Si il vous reste encore du temps, on peut remarquer que si on appelle map sur une suite
qui est elle même issue d'un map, c'est équivalent à appeler map une seule fois
avec la composition des deux fonctions de chaque appel à map en argument.
Implanter cette optimisation.
-
En fait, il n'est pas nécessaire de faire la première question car celle-ci ne rapporte pas de point,
c'est juste pour voir si vous lisez bien les sujets jusqu'au bout !
© Université de Marne-la-Vallée