:: Enseignements :: ESIPE :: E4INFO :: 2019-2020 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Examen de Java Avancé |
Le but de ce TP noté est d'implanter un conteneur non mutable d'objets triés et non nuls, représenté par l'interface Vec.
Cette interface devra posséder deux implantations, Mono qui représente un conteneur à zéro ou un élément et
Fixed qui représente un conteneur ayant un nombre fixe d'éléments.
Vos sources Java produites pendant l'examen devront être placées sous le répertoire EXAM de votre compte ($HOME)
(qui est vide dans l'environnement de TP noté). Sinon, elles ne seront pas récupérées.
Tout document papier est proscrit.
Vous pouvez consulter la javadoc à travers Eclipse (onglet Javadoc), en utilisant
jdoc dans un terminal
Sinon la doc est là:
/usr/local/apps/java13/docs/api/index.html.
Les seuls documents électroniques autorisés sont les supports de cours à l'url
http://igm.univ-mlv.fr/~forax/ens/java-avance/cours/pdf/.
Vous avez le droit de lire le sujet jusqu'au bout, cela vous donnera une bonne idée de là où on veut aller !
Exercice 1 - Vec
L'interface
Vec est un conteneur qui maintient ses éléments triés avec cinq opérations de base
-
size qui renvoie le nombre d'éléments dans le conteneur.
-
comparator qui renvoie comment les éléments du conteneur doivent être comparées deux à deux (c'est à dire un objet de la classe Comparator).
-
min qui renvoie l'élément minimum si il existe.
-
max qui renvoie l'élément maximum si il existe
-
une opération qui permet de parcourir les éléments de façon triée.
De plus, l'interface
Vec possède
-
deux méthodes mono permettant de créer une instance de la classe Mono (qui implémente l'interface Vec)
avec zéro ou un élément
-
et une méthode fixed permettant de créer une instance de la classe Fixed (qui implémente l'interface Vec), avec une nombre fixé d'éléments.
L'interface
Vec est paramétrée par le type des éléments du conteneur et ses implantations interdisent le stockage de la valeur
null.
Voici quelques exemples d'utilisation de l'interface
Vec. L'une des méthodes
mono permet de créer une instance de la classe
Mono stockant une fonction de comparaison et un seul élément et l'autre méthode fait la même chose, mais sans élément.
Mono<String> mono0 = Vec.mono(String::compareTo);
Mono<String> mono1 = Vec.mono(String::compareTo, "hello mono");
La méthode
fixed permet de créer une instance de la classe
Fixed stockant une fonction de comparaison et plusieurs éléments.
Fixed<String> fixed = Vec.fixed(String::compareTo, "hello", "fixed", "!");
Sur un
Vec, il est possible de demander le minimum ou le maximum, par exemple:
var maximum = fixed.max();
System.out.println(maximum.isPresent()); // true, fixed à bien un maximum
System.out.println(maximum.orElseThrow()); // hello, la valeur du maximum
Des tests unitaires correspondant à l'implantation sont ici:
VecTest.java.
-
Créer l'interface Vec avec les méthodes size et comparator.
Puis, dans l'interface Vec, implanter chaque méthode mono qui prend en paramètre
un ordre de comparaison et éventuellement un élément et renvoie un Mono contenant ces valeurs.
Faire en sorte que l'on ne puisse créer des objets Mono qu'en passant par une des méthodes mono de l'interface.
Enfin, implanter les méthodes size et comparator dans la classe Mono.
Vérifier que votre code passe les tests JUnit marqué "Q1".
-
Implanter la méthode fixed dans l'interface Vec qui prend en paramètre un ordre de comparaison suivi des différents éléments séparés par des virgules.
Créer la classe Fixed et implanter les méthodes size et comparator de cette classe.
Vérifier que votre code passe les tests JUnit marqué "Q2".
-
Écrire les méthodes min et max dans la classe Mono sachant que ces deux méthodes
renvoient un objet java.util.Optional pour indiquer qu'il peut ne pas y avoir de résultat.
Vérifier que votre code passe les tests JUnit marqué "Q3".
-
On souhaite ajouter les méthodes min et max dans l'interface Vec.
Pour cela, il faut implanter ces méthodes dans la classe Fixed. Sachant que l'on doit garder les éléments triés, le minimum et le maximum sont facilement accessibles.
Cependant, on peut remarquer qu'il n'est pas nécessaire de trier les éléments si on demande juste la taille du Fixed (en appelant size).
Vous devez donc faire en sorte de ne pas trier les éléments à la création du Fixed mais seulement quand c'est nécessaire, par exemple la première fois que l'on demande un minimum ou un maximum.
Implanter les méthodes min et max.
Vérifier que votre code passe les tests JUnit marqué "Q4".
Note : on peut remarquer que le code de min et le code max sont extrêmement similaires à part que le minimum est le premier élément tandis que le maximum est le dernier, une fois les éléments triés.
On peut donc écrire une méthode intermédiaire de partage de code.
-
On veut maintenant pouvoir parcourir n'importe quel Vec en utilisant la boucle for each in (le for deux points) de Java, de telle façon que le code suivant fonctionne (n'oubliez pas que les éléments du Vec doivent apparaître triés).
Vec<String> vec = ...
for(String element: vec) {
...
}
Modifier votre code et vérifier qu'il passe les tests JUnit marqué "Q5".
-
On souhaite ajouter une méthode permettant de renvoyer un Stream des éléments contenus dans un Vec.
Pour celà, on peut remarquer qu'il suffit d'utiliser le code générique ci-dessous directement sur un Vec
public Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Faire en sorte que ce code ne soit pas dupliqué dans les implantations
et vérifier que votre code passe bien les tests marqués "Q6".
-
On veut ajouter à l'interface Vec une méthode toMono qui prend en paramètre un ordre de comparaison
et un Stream d'éléments et créé un objet Mono à partir de ces deux informations.
Que doit-on faire si le Stream contient plus d'éléments que peut en contenir un Mono ?
Comment faire pour ne pas calculer tous les éléments du Stream s'ils sont trop nombreux ?
Implanter la méthode toMono et vérifier que votre code passe bien les tests marqués "Q7".
-
Implanter une méthode toFixed qui prend en paramètre un ordre de comparaison
et un Stream d'éléments et créé un objet Fixed.
Vérifier que votre code passe bien les tests marqués "Q8".
-
On souhaite maintenant écrire une méthode filter sur un Vec qui prend en paramètre une fonction f
qui elle même prend un élément du Vec en paramètre et renvoie un booléen.
La méthode filter renvoie un nouveau Vec contenant les éléments pour lesquels f renvoie true.
On souhaite, de plus, choisir quelle implantation de Vec va être renvoyée en utilisant en second paramètre
une des méthodes toMono ou toFixed précédemment écrites.
Par exemple, le code suivant prend toutes les chaînes de caractères commençant par "v" et les stocke dans un Fixed
Vec<String> vec = ...
Fixed<String> fixed = vec.filter(s -> s.startsWith("v"), Vec::toFixed);
Voici un autre exemple qui prend toutes les chaînes de caractères commençant par "v" et les stocke dans un Mono
Vec<String> vec = ...
Mono<String> mono = vec.filter(s -> s.startsWith("v"), Vec::toMono);
Écrire le code de la méthode filter en évitant la duplication de code.
Vérifier que votre code passe bien les tests marqués "Q9".
-
Enfin, on souhaite ajouter une méthode filter à un seul paramètre qui crée dans ce cas un conteneur de la même classe que le conteneur sur lequel
on appelle la méthode.
Par exemple, si on appelle filter sur un Mono, le résultat est un Mono.
Mono<String> mono = ...
Mono<String> mono2 = mono.filter(s -> s.startsWith("v"));
Implanter cette méthode en essayant d'écrire le code le plus simple possible.
Vérifier que votre code passe bien les tests marqués "Q10".
© Université de Marne-la-Vallée