:: Enseignements :: ESIPE :: E4INFO :: 2025-2026 :: Java Avancé ::
![[LOGO]](http://monge.univ-eiffel.fr/ens/resources/mlv.png) | Examen de Java Avancé 2025 - 2026 - session 2 |
Le but de ce TP noté est d'implanter une classe Vec qui est une structure de données
qui permet l'insertion d'éléments à n'importe quel endroit et offre une
vue non-modifiable de type java.util.List.
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.
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
La classe Vec est une classe qui stocke des éléments non nuls.
L'implantation de Vec garanti l'ordre d'insertion.
La classe
Vec possède les opérations suivantes :
-
un constructeur qui créé une instance à partir d'éléments passés
en paramètre.
-
une méthode d'affichage qui affiche les éléments séparés par des virgules.
-
la méthode add(int index, element) qui ajoute un élément à un index
particulier (cela peut être devant tous les éléments, à la fin de tous les éléments
ou au milieu).
-
Les méthodes spliterator() et stream() qui renvoie les éléments
dans l'ordre d'insertion.
-
la méthode asList() qui renvoie une vue non-modifiable des éléments
du Vec. Si le Vec est altéré à postériori, alors la vue ne permet
plus d'accéder aux éléments.
Voici un exemple d'utilisation
Vec<String> vec = new Vec<String>("a");
vec.add(1, "b");
vec.add(0, "c");
IO.println(vec); // c, a, b
IO.println(map.stream().toList()); // [c, a, b]
List<String> view = vec.asList();
IO.println(view); // [c, a, b]
vec.add(0, "d");
IO.println(view); // ConcurrentModificationException
Dans l'exemple ci-dessus, la vue
view est créé sur le
vec,
si celui-ci change (ici, on ajoute "d" devant), alors la vue devient invalide
et il n'est plus possible de lire ses éléments.
L'exception
ConcurrentModificationException est levée lors que l'on
essaye d'accéder aux éléments.
En termes d'implantation, les éléments sont stokés dans un tableau et on utilise
un champ size pour savoir combien il y a d'éléments insérés dans le tableau.
Des tests unitaires correspondant à l'implantation sont ici :
VecTest.java
Note : comme on utilise les tests unitaires JUnit sans Maven, dans la configuration de votre projet, il faut ajouter
la librairie JUnit 5, soit à partir du fichier
VecTest.java, en cliquant sur l'annotation
@Test et en sélectionnant le quickfix "Fixup project ...", soit en sélectionnant les "Properties" du projet
(avec le bouton droit de la souris sur le projet) puis en ajoutant la librairie JUnit 5 (jupiter) au ClassPath.
-
Dans un premier temps, on veut implanter seulement le constructeur ainsi
que la méthode d'affichage.
A la création, le constructeur doit permettre de passer en paramètres des valeurs
séparées par des virgules.
La méthode d'affichage doit être implantée avec un StringJoiner
ou un StringBuilder à votre convenance.
Attention à ce que votre implantation respected bien le principe d'encapsulation.
Écrire la classe Vec, son constructeur et sa méthode d'affichage.
Vérifier que les tests marqués "Q1" passent.
-
On souhaite changer la méthode d'affichage pour utiliser un stream.
Mettre en commentaire votre ancien code.
Écrire une nouvelle implantation de la méthode d'affichage en utilisant un stream.
Vérifier que les tests marqués "Q2" passent.
-
On souhaite maintenant pouvoir ajouter des élements en utilisant
la méthode add(inde, element).
Si on insère un élément avant des éléments existants,
ceux-ci sont décalés sur droite.
Si il n'y a plus de place dans le tableau, celui-ci doit doubler sa taille.
Attention, lors de la création, le tableau doit avoir la même taille que les éléments
passés en paramètre, ce n'est que si on utilise la méthode add
que le redimensionnement doit être fait.
Vérifier que les tests marqués "Q3" passent.
-
Vérifier que le code que vous avez écrit marche si l'on ajoute
des éléments avec add(index, element) à un Vec
vide au début.
Vérifier que les tests marqués "Q4" passent.
-
On souhaite implanter les méthodes spliterator() et stream()
qui renvoi tous les éléments du Vec.
Pour cela, écrivez votre propre Spliterator
sachant que l'on ne s'intéresse qu'à la partie séquentielle.
Attention, c'est la question qui vaut le plus de points de tout le TP.
Vérifier que les tests marqués "Q5" passent.
Il est possible que certains tests ne soient pas présents parmi les
tests que l'on vous a fournis. A vous de garantir que votre implantation
est correcte.
-
On peut remarquer que l'on peut créer un stream sur un Vec
puis modifier le Vec avant d'utiliser le stream pour
faire un parcours. Dans ce cas où l'on essaye d'accéder
à un élément alors que le Vec sous-jacent a été modifié,
une exception ConcurrentModificationException doit être levée.
On peut noter que l'on peut facilement savoir si le Vec sous-jacent
a été modifié sans pour autant ajouter un ou des champs supplémentaire.
Modifier votre implantation pour avoir le comportement attendu.
Vérifier que les tests marqués "Q6" passent.
-
On souhaite maintenant implanter la méthode asList()
qui renvoie une vue non-modifiable du Vec
sur lequel asList est appelée.
Implanter la méthode asList().
Rappel: L'API de Java (le JDK) possède définie la classe
AbstractList pour cela.
Vérifier que les tests marqués "Q7" passent.
-
On souhaite qu'accéder aux éléments du Vec à travers la vue
ne soit pas possible si le Vec a été modifié après la création
de la vue.
Faite les changements qui s'imposent.
Vérifier que les tests marqués "Q8" passent.
-
Enfin, vérifier qu'il n'est pas possible d'accéder aux éléments
d'une vue invalidée si on appéle la métode stream
sur la vue.
Vérifier que les tests marqués "Q9" passent.
© Université de Marne-la-Vallée