:: Enseignements :: ESIPE :: E3INFO :: 2021-2022 :: Programmation Objet avec Java ::
[LOGO]

Paquetage, Structure de données, Relation d'implantation


Exercice 1 - Les listes chaînées

Le but de cet exercice est d'écrire une implantation de listes chaînées.

Pour la suite de l'exercice, l'ensemble des classes créées devront être dans le paquetage fr.umlv.data. Les fichiers sources (.java) doivent être dans le répertoire src et les fichiers destinations (.class) doivent être dans le répertoire classes.
Si ce n'est pas le cas, configurer votre Eclipse dans Window > Preferences > Java > Build Path et dans project > Properties > Java > Build Path.

Nous allons dans un premier temps créer une liste chaînée d'entiers.

  1. Créer un record Link dans le paquetage fr.umlv.data correspondant à un maillon de la liste chaînée stockant des entiers.
    En aucun cas, l'utilisateur de la classe ne devra lui-même manipuler des maillons.
    Quelle doit être la visibilité du record fr.umlv.data.Link ?
    Écrire un main de test dans cette classe créant deux maillons contenant les valeurs 13 et 144.
  2. Quelle est la commande pour exécuter le main du record fr.umlv.data.Link à partir d'un terminal (pas dans Eclipse) ?
  3. Créer une classe fr.umlv.data.LinkedLink qui permettra de manipuler une liste chainée par son premier maillon, avec ses méthodes :
    1. add(int value) qui ajoute un élément en tête de la liste.
    2. Ecrire une méthode get(index) qui renvoie l'élément à l'index (en commençant à 0).
      Comment faire en sorte que code qui vérifie que l'index est valide soit en O(1) ?
      Faite les changements qui s'imposent.
    3. forEach(lambda) qui appel la lambda avec la valeur de chaque maillon de la liste.
    4. Ecrire une méthode d'affichage habituelle qui affiche la liste chainée avec des "-->" entre les valeurs.
      Par avec une liste contenant les éléments 3, 2 et 1, on obtient
                1 --> 2 --> 3
              
      Note: il existe une classe StringMerger qui prend à la constructeur un délimiteur et qui va appliquer le délimiteur entre les chaines de caractère ajoutées avec add.
      En option: il est possible d'écrire une version avec un stream soit en utilisant la version la 3 paramètre de Stream.iterate() soit en utilisant Stream.mapMulti() !
Pour tester la classe fr.umlv.data.LinkedLink, créer une classe Main dans le package fr.umlv.data.main.

Exercice 2 - Liste chaînée (suite)

  1. Dans le but de pouvoir ré-utiliser la liste dans différents codes, changer les classes fr.umlv.data.LinkedLink et fr.umlv.data.Link pour une implantation plus générique à base d'Object.
  2. Dans la classe Main, expliquer pourquoi le code suivant ne fonctionne pas ?
           var l = new LinkedLink();
           l.add("hello");
           l.add("world");
           l.forEach(s -> System.out.println("string " + s + " length " + s.length));
         
    Que doit-on faire pour que le code fonctionne

Exercice 3 - Générification de LinkedLink

Le but de cet exercice est de "générifier" les classes fr.umlv.data.LinkedLink et fr.umlv.data.Link

  1. Rappeler quel est l'intérêt d'utiliser un type paramétré ici ?
  2. Paramétrer la classe fr.umlv.data.LinkedLink pour que celle-ci soit générique.
  3. Modifier la classe fr.umlv.data.main.Main en conséquence.
  4. Optionnellement, pour les plus balèzes, écrire une méthode removeIf qui supprime tous les élements vrai pour un prédicat.
    Par exemple, pour supprimer tous les éléments paires d'une liste
          var l = new LinkedLink<Integer>();
          l.add(24);
          l.add(17);
          l.add(12);
          l.removeIf(i -> i % 2 == 0);
          System.out.println(l); // 17
         
    Note: l'astuce est d'utiliser un appel récursif et de re-créer une nouvelle liste lors de la remonter.