:: Enseignements :: ESIPE :: E4INFO :: 2025-2026 :: Java Avancé ::
![[LOGO]](http://monge.univ-eiffel.fr/ens/resources/mlv.png) | Examen de Java Avancé 2025 - 2026 |
Le but de ce TP noté est d'implanter une classe DeferredVec qui est une liste d'éléments
qui, lors d'une suppression, marque les éléments comme ``à supprimer'' au lieu de les supprimer directement.
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 - DeferredVec
La classe DeferredVec est une classe qui stocke des éléments non nuls.
L'ajout se fait en conservant l'ordre d'insertion.
L'accès aux éléments peut se faire en utilisant un index, vec.get(index)
La suppression se fait de façon différée (deferred en anglais). Dans un premier temps, les éléments sont
marqués pour la suppression, puis ceux-ci peuvent être effectivement supprimés avec la méthode vec.compact()
ou alors "dé-supprimés" en utilisant la méthode vec.undo().
La classe
DeferredVec possède les opérations suivantes :
-
un constructeur qui permet de créer un DeferredVec vide,
-
la méthode add(element) qui permet d'ajouter un élément,
-
la méthode size qui renvoie le nombre d'éléments (marqués ou pas),
-
la méthode get(index) qui renvoie l'élément à l'index index
sauf si l'élément est marqué comme à supprimer,
-
la méthode remove(index) qui marque l'élément à supprimer,
sauf si l'élément est déjà marqué comme à supprimer,
-
la méthode compact() qui supprime tous les éléments marqués à supprimer,
-
la méthode undo() qui supprime toutes les marques de suppression.
Des tests unitaires correspondant à l'implantation sont ici :
DeferredVecTest.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
DeferredVecTest.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 pouvoir créer des instances de DeferredVec,
pouvoir ajouter des éléments avec add, obtenir un élément avec get(index) et
connaître le nombre d'éléments avec size.
L'implantation doit stocker des éléments dans un tableau
de taille 8. Pour l'instant, on ne s'occupe pas de redimensionner
le tableau automatiquement.
Écrire la classe DeferredVec, son constructeur, ses méthodes add,
get et size.
Vérifier que les tests marqués "Q1" passent.
-
On veut maintenant que le tableau se redimensionne automatiquement si on veut stocker plus d'éléments
que la capacité actuelle du tableau. Le redimensionnement se fait en multipliant la capacité
du tableau par 2.
Ici, on ne s'occupera pas de la gestion de l'overflow.
Modifier le code de la classe DeferredVec en conséquence.
Vérifier que les tests marqués "Q2" passent.
-
On souhaite ajouter les méthodes remove(index) et undo().
La méthode remove(index) marque élément à l'index index
à supprimer et renvoie l'élément.
La méthode undo() supprime toutes les marques de suppressions.
En termes d'implantation, vous utiliserez une instance de la classe java.util.BitSet
pour marquer les éléments à supprimer.
La classe BitSet possède les méthodes get(index), set(index),
clear(from, to) et clear().
Attention, il ne doit pas être possible d'accéder à un élément en utilisant
get(index) si celui-ci est marqué pour la suppression. Même chose
pour remove(index), il ne doit pas être possible de marquer pour la
suppression un élément déjà marqué pour la suppression.
Modifier le code de la classe DeferredVec et ajouter les méthodes
remove et undo
Vérifier que les tests marqués "Q3" passent.
-
On souhaite maintenant écrire la méthode compact
qui supprime tous les éléments marqués et décale les éléments non-marqués
sur la gauche (de sorte qu'il n'y ait pas de trous).
En termes d'algorithme, l'idée est d'avoir deux curseurs,
un qui parcourt tous les éléments et un qui correspond à l'endroit où il faut
insérer le prochain élément non-marqué. Donc, on peut parcourir tous
les éléments et n'ajouter que les éléments qui ne sont pas marqués.
Et il faut faire attention à ne pas créer de memory leak.
Implanter la méthode compact.
Vérifier que les tests marqués "Q4" passent.
-
On veut écrire une méthode eachState(function) qui parcours
chaque élément et indique l'élément et son statut : removed ou pas
(un booléen).
Voici un exemple d'utilisation :
var vec = new DeferredVec<String>();
vec.add("first");
vec.add("second");
vec.add("third");
vec.add("fourth");
vec.remove(1);
vec.remove(3);
vec.eachState((element, removed) -> {
IO.println(element + " " + removed);
});
// first false
// second true
// third false
// fourth true
En termes d'implantation, on vous demande d'utiliser un Stream,
si vous n'y arrivez pas, faites autrement.
Implanter la méthode eachState(function).
Vérifier que les tests marqués "Q5" passent.
-
On souhaite pouvoir parcourir un DeferredVec en utilisant
une boucle. Dans ce cas, seuls les éléments non-marqués seront
parcourus.
Par exemple :
var vec = new DeferredVec<String>();
vec.add("first");
vec.add("second");
vec.add("third");
vec.add("fourth");
vec.remove(1);
vec.remove(2);
for (String element : vec) {
IO.println(element);
}
// first
// fourth
De plus, on souhaite que si l'on supprime les éléments en utilisant l'itérateur,
les éléments soient uniquement marqués pour la suppression.
Modifier la classe DeferredVec en conséquence.
Vérifier que les tests marqués "Q6" passent.
-
On veut ajouter une surcharge à la méthode compact,
compact(from, to) qui compacte uniquement les éléments entre
les index from inclus et to exclu.
Implanter la méthode compact(from, to).
Vérifier que les tests marqués "Q7" passent.
-
On souhaite ajouter la méthode stream qui permet de parcourir
tous les éléments non-marqués.
Écrire la méthode stream sachant que seule la version séquentielle
nous intéresse pour l'instant.
Vérifier que les tests marqués "Q8" passent.
Note : votre implantation de Stream devrait être plus efficace
si aucun éléments n'est marqués pour la suppression.
-
Modifier l'implantation de la méthode stream()
pour que l'implantation parallèle marche aussi.
Vérifier que les tests marqués "Q9" passent.
© Université de Marne-la-Vallée