:: Enseignements :: Master :: M1 :: 2025-2026 :: Java Avancé ::
![[LOGO]](http://monge.univ-eiffel.fr/ens/resources/mlv.png) | Examen de Java Avancé 2025 - 2026 - session 1 |
Le but de ce TP noté est d'implanter une classe IndexedMap qui est une liste non modifiable
d'éléments que l'on veut voir comme une Map.
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 - IndexedMap
La classe IndexedMap est une classe générique non modifiable qui stocke des éléments non nuls,
chaque élément possède un index, 0 pour le premier élément, 1 pour le second, etc...,
et cet index est utilisé pour obtenir les éléments.
Après une première implantation, notre but sera de rendre cette classe efficace en termes de performance.
La classe
IndexedMap possède les opérations suivantes :
-
un méthode of(element0, element1, ...) qui créé une instance de
IndexedMap initialisée avec ces éléments.
-
la méthode size qui renvoie le nombre d'éléments.
-
la méthode getValueOrDefault(index, defaultValue) qui permet d'obtenir un
élément en fonction de son index, ou qui renvoie la valeur par défaut s'il n'y a
pas d'élément à l'index indiqué.
-
une méthode keySet qui renvoie un ensemble des index valides, par exemple,
si une IndexedMap possède 3 éléments, keySet renvoie l'ensemble
(0, 1, 2).
-
la méthode values() qui renvoie une liste des éléments.
-
la méthode forEach(function) qui appelle la fonction avec l'index
de l'élément ainsi que l'élément pour chaque élément dans l'IndexedMap.
-
la méthode stream() qui renvoie les couples index/élément pour
chaque élément sous forme d'un Stream.
Voici un exemple d'utilisation
var map = IndexedMap.of("apple", "banana", "cherry");
IO.println(map.size()); // 3
IO.println(map.getValueOrDefault(0, "default")); // apple
IO.println(map.keySet()); // [0, 1, 2]
IO.println(map.values()); // [apple, banana, cherry]
IO.println(map.get(1)); // banana
IO.println(map.stream().map(e -> "" + e).toList()); // [0=apple, 1=banana, 2=cherry]
Des tests unitaires correspondant à l'implantation sont ici :
IndexedMapTest.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
IndexedMapTest.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 la méthode of() pour créer des instances
de IndexedMap ainsi que les méthodes size() et getValueOrDefault().
L'implantation doit utiliser une java.util.List en interne,
pour stocker les éléments.
Écrire la classe IndexedMap, sa méthode of, ses méthodes size
et getValueOrDefault.
Vérifier que les tests marqués "Q1" passent.
-
On souhaite maintenant implanter la méthode keySet() qui renvoie l'ensemble des
index pour les éléments de l'IndexedMap sous forme d'une vue.
Implanter la méthode keySet().
Vérifier que les tests marqués "Q2" passent.
Rappel : en Java, on peut implanter facilement l'interface Set en utilisant la classe
abstraite AbstractSet (de même pour List et AbstractList et
Map et AbstractMap).
-
On souhaite implanter la méthode values qui renvoie une liste non-modifiable
des éléments sous forme d'une vue.
Implanter la méthode values.
Vérifier que les tests marqués "Q3" passent.
-
On souhaite ajouter une méthode forEach(function)
qui, pour chaque élément, appelle la fonction avec en premier paramètre l'index
et en second paramètre l'élément.
Quelle interface fonctionnelle doit-on utiliser ici, sachant que l'on permet le boxing,
car dans le futur, on voudra implanter l'interface Map (cf. question suivante).
Implanter la méthode forEach().
Vérifier que les tests marqués "Q4" passent.
-
On souhaite maintenant que IndexMap implante l'interface
Map.
Modifier le code de la classe IndexMap en conséquence.
Vérifier que les tests marqués "Q5" passent.
-
Si vous ne l'avez pas déjà fait à la question précédente,
les méthodes get() et getOrDefault() n'ont pas la
bonne complexité pire cas, comment doit-on résoudre ce problème ?
Faire les changements qui s'imposent.
Vérifier que les tests marqués "Q6" passent.
-
En fait, les deux méthodes précédentes en sont pas les seules qui n'ont
pas la bonne complexité.
Regarder les tests, en déduire en les méthodes qui n'ont pas la bonne
complexité et corriger cela.
Vérifier que les tests marqués "Q7" passent.
-
On souhaite ajouter une méthode stream() qui renvoie les couples
index/éléments dans le même ordre que la méthode forEach().
Implanter la méthode stream() sachant que pour l'instant seule
la version séquentielle nous intéresse.
Vérifier que les tests marqués "Q8" passent.
-
Modifier l'implantation précédente pour que l'implantation parallèle
sépare bien les Spliterator en deux indépendamment du nombre d'éléments
(supérieur à 1).
Vérifier que les tests marqués "Q9" passent.
© Université de Marne-la-Vallée