:: Enseignements :: Master :: M1 :: 2023-2024 :: Java Avancé ::
[LOGO]

Examen intermédiaire de Java Avancé 2023


Le but de ce TP noté est d'implanter une classe Cord (une corde) qui un conteneur mutable d'objets qui permet de voir les éléments en ordre inverse de leur ordre d'insertion (comme une pile) et que l'on peut attacher à une autre corde.

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.
La javadoc 21 est https://igm.univ-mlv.fr/~juge/javadoc-21/.
Les seuls documents électroniques autorisés sont les supports de cours à l'URL http://igm.univ-mlv.fr/~forax/ens/java-avance/cours/pdf/.

Comme nous utilisons Java 21 donc vous devez configurer votre Eclipse pour cela :
Dans Window > Preferences > Java > Installed JREs: vous devez ajouter Java 21 qui est disponible sur vos machines dans le répertoire /usr/local/apps/java21
Dans Window > Preferences > Java >Compiler le niveau compiler compliance level doit être 21.

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 - Cord

Cord est une classe paramétrée par le type des éléments que l'on va stocker dedans. Les éléments ne peuvent pas être null.
  • La classe Cord possède un constructeur sans paramètre.
  • La méthode add permet d'ajouter un élément en haut de la corde.
  • La méthode get(index) permet d'accéder à l'élément à l'index pris en paramètre. L'index 0 correspond au dernier élément inséré (celui du haut), l'index 1 correspond à l'avant-dernier élément inséré, etc.
  • La méthode forEachIndexed(function) appelle la méthode function avec l'index de l'élément et l'élément lui-même pour tous les éléments dans le même ordre que get(index), donc dans l'ordre inverse que l'ordre d'insertion.
  • La méthode createChild permet de créer une nouvelle corde fille. Une corde fille accède à ses éléments (en sens inverse) suivi des éléments de la corde mère (eux aussi en sens inverse). Donc, lors d'un appel à get() ou forEachIndexed, on cherche d'abord dans les éléments de la corde courante puis dans les éléments de la corde mère.
  • Il doit être possible de parcourir une corde (et ses cordes mères) avec une boucle for.
  • La méthode attachParent permet d'attacher une corde mère à une corde n'ayant pas déjà une corde mère.
  • La méthode indexedElements permet de voir les éléments (et leur index) sous forme d'un Stream.

Voici des exemples d'utilisation
Cord<Integer> cord = new Cord<Integer>();
cord.add(3);
cord.add(17);
System.out.println(cord.get(0));  // 17
System.out.println(cord.get(1));  // 3
     
On peut remarquer que get() renvoie les valeurs dans l'ordre inverse de l'ordre d'insertion (l'ordre d'appel des méthodes add).
 parent.forEachIndexed((index, element) -> {
     System.out.println(index + " " + element);
 });  // 0 17
      // 1 3
     
De même, forEachIndexed() appelle la lambda avec les éléments dans l'ordre inverse de l'ordre d'insertion.
Cord<Integer> child = cord.createChild();
child.add(116);
System.out.println(child.get(0)); // 116
System.out.println(child.get(1)); // 17
System.out.println(child.get(2)); // 3
     
La méthode createChild crée une corde fille child qui peut accéder à ses propres éléments et à ceux de la corde mère (ici cord).
De plus, si on ajoute un élément à la corde mère (ici cord), la modification sera visible dans la cord fille.
cord.add(8234);
for(int element : child) {
    System.out.println(element);
}  // 116
   // 8234
   // 17
   // 3
     
Faire une boucle sur une corde parcourt (toujours dans l'ordre inverse de l'ordre d'insertion) les cordes filles avant les cordes mères.

Des tests unitaires correspondant à l'implantation sont ici : CordTest.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 CordTest.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.

  1. On souhaite créer la classe Cord avec un constructeur sans paramètre. En terme d'implantation, une corde doit stocker ses éléments dans une liste (java.util.List) implantée avec un tableau dynamique (qui s'agrandit tout seul lorsque c'est nécessaire). On souhaite de plus créer les les méthodes add et get(index) qui permettent respectivement d'ajouter un élément à la fin et d'accéder un élément à un index (en partant de la fin, l'index 0 correspond au dernier élément).
    Écrire la classe Cord et ses méthodes add et get(index).
    Vérifier que les tests marqués "Q1" passent.
    Note : si cela vous aide, il existe une méthode reversed() sur l'interface java.util.List.

  2. On souhaite écrire une méthode forEachIndexed(function) qui prend en paramètre une fonction avec deux paramètres et appelle celle-ci avec l'index et l'élément de chaque élément de la corde. Comme avec get, l'ordre des éléments est l'ordre inverse de l'ordre d'insertion.
    Écrire la méthode forEachIndexed.
    Vérifier que les tests marqués "Q2" passent.
    Note : éviter le boxing inutile SVP !

  3. On souhaite écrire une méthode createChild qui crée une nouvelle corde fille à laquelle on attache la corde courante (celle sur laquelle on a appelée la méthode createChild) qui devient sa mère. On souhaite de plus, changer le code de get(index) pour que cette méthode permette d'accéder aux éléments de la corde courante puis aux éléments de la corde mère, et de la corde mère de la corde mère, etc... (cf. exemple plus haut).
    Modifier le code de le classe Cord pour ajouter la méthode createChild.
    Vérifier que les tests marqués "Q3" passent.
    Note : on ne vous demande pas de mettre à jour l'implantation de forEachIndexed, pour l'instant.
    Note 2 : si le code de get() est récursif, vous aurez beaucoup de mal à faire les questions suivantes.

  4. On souhaite maintenant mettre à jour la méthode forEachIndexed (comme pour la méthode get() à la question précédente) afin de parcourir aussi les éléments de la corde mère.
    Vérifier que les tests marqués "Q4" passent.

  5. On souhaite pouvoir parcourir une corde (et ses cordes mère, grand-mère, etc) en utilisant la boucle "for" de Java comme dans l'exemple ci-dessus. Pour l'instant, on va supposer qu'une corde a toujours au moins un élément.
    Modifier le code de Cord pour pouvoir parcourir les éléments avec une boucle "for".
    Vérifier que les tests marqués "Q5" passent.

  6. Si vous êtes balèzes, modifier votre code pour que le parcours fonctionne aussi dans le cas où une corde (ou une corde mère, etc) est vide. Sinon, passer à la question suivante.
    Vérifier que les tests marqués "Q6" passent.

  7. On souhaite ajouter une méthode attachParent(parent) qui permet d'attacher une corde mère à la corde courante, si la corde courante n'a pas déjà une corde mère.
    Écrire la méthode attachParent.
    Vérifier que les tests marqués "Q7" passent.

  8. En fait, la méthode attachParent introduite précédemment a un problème, elle permet de créer, si on suit les cordes mères, des cycles où l'on retombe sur la corde initiale. On se propose de détecter ce cas et d'empêcher l'attachement dans ce cas.
    Changer le code de attachParent pour détecter les cycles.
    Vérifier que les tests marqués "Q8" passent.

  9. Enfin, on souhaite créer une méthode indexedElements qui renvoie un Stream d'objets ayant deux méthodes index() qui renvoie l'index de l'élément et element qui renvoie l'élément dans le même ordre que forEachIndexed.
    On ne vous demande pas ici, d'implanter votre propre Stream, car nous n'avons pas encore vu en cours comment faire, mais d'utiliser les méthodes que nous avons déjà vues pour créer le Stream.
    Écrire la méthode indexedElements().
    Vérifier que les tests marqués "Q9" passent.
    Indice : on peut utiliser mapMulti() pour propager les valeurs de forEachIndexed.