:: Enseignements :: Licence :: L3 :: 2024-2025 :: Programmation Objet avec Java ::
[LOGO]

Objets, délégation, ArrayList, HashMap


Exercice 1 - Eclipse

À partir de maintenant, nous allons utiliser Eclipse (lancer la commande eclipse dans un terminal) comme environnement pour faire les TPs.
  1. Créer un projet nommé TP4.
  2. Modifier les propriétés du projet TP4 pour que les classes (fichiers .java) soit stockées dans le répertoire sources.
  3. Faire de même pour tous les futurs projets qui seront créés (Aller voir dans le menu Window > Preferences).
  4. Vérifier que l'environnement d'exécution est bien Java-23 ; changer si ce n'est pas le cas. Pour les machines de la fac, le JDK 23 est situé dans /usr/local/apps/java23.
  5. Vérifier que la version pour la compilation est bien 23 (dans les paramètres du compilateur) ; changer si ce n'est pas le cas.
  6. Écrire une classe Main qui affiche Hello Eclipse.
  7. A faire à la maison pour le compte rendu :
    1. Que fait sysout + Ctrl + Space dans un main ?
    2. Que fait toStr + Ctrl + Space dans une classe ?
    3. Définir un champs foo de type int, que fait get + Ctrl + Space, et set + Ctrl + Space .
    4. Dans le menu Source, comment générer un constructeur initialisant le champ foo ?
    5. Sélectionner le nom de la classe puis Alt + Shift + R, qu'obtient-on ? Même question avec le champ foo .
    6. Écrire a = 2 + 3 + 4, puis sélectionner 2 + 3 puis Alt + Shift + L .
    7. Écrire new Integer(2), en gardant le curseur après ')', appuyer sur Ctrl + Shift + 1, que se passe-t-il ?
    8. Déclarer une variable s de type String et cliquer sur String en maintenant la touche Ctrl . Que se passe-t-il ?
    9. Dans la méthode toString(), que fait un Ctrl + Clic sur super.toString() ?
    10. Sélectionner le champs foo, puis Ctrl + Shift + G. Que se passe-t-il ?
    11. À quoi sert Ctrl + Shift + O ?
    12. À quoi sert Ctrl + Shift + C ?

    Apprenez les raccourcis que nous venons de voir, cela vous fera gagner du temps lors des TPs notés.

Exercice 2 - Library

On souhaite écrire une classe Library pour modéliser une bibliothèque et permettant de stocker des livres, de telle façon que le code suivant fonctionne :
  public class Main {
    public static void main(String[] args) {
      var book = new Book("Da Vinci Code", "Ban Brown");
      var library = new Library();
      library.add(book);
      System.out.println(library.findByTitle("Da Vinci Code"));
    }
  }
   
La classe Main doit être dans le package par défaut (directement dans src).
Pour stocker les livres, nous allons utiliser la classe java.util.ArrayList qui est une implantation d'un tableau dynamique (qui s'agrandit si nécessaire).

Vous utiliserez le record Book suivant
    package fr.uge.library;

    public record Book(String title, String author) {
      public Book {
        Objects.requireNonNull(title);
        Objects.requireNonNull(author);
      }
     
      @Override
      public String toString() {
        return title + " by " + author;
      }
    }
   
Avec Eclipse, faire un copier-coller du code ci-dessus dans le répertoire src (oui, ça fonctionne !).

  1. A quoi sert un package (ici le package fr.uge.library) ?
    Dans un code source, comment déclarer qu'une classe vient d'un package particulier ?

  2. Dans le package fr.uge.library, écrire une classe Library avec un champ books de type ArrayList ainsi qu'un constructeur sans paramètre initialisant le champ books.
    Attention à déclarer les bons modificateurs de visibilité pour le champ books.
    Note : il est possible que le compilateur lève un warning suite à un problème de typage au niveau de la déclaration et/ou de l'allocation de l'ArrayList. Si c'est le cas, comment corriger le problème ?

  3. Ajouter une méthode add qui permet d'ajouter des books (non null) à la liste de livres.

  4. Écrire une méthode findByTitle qui permet de trouver un livre en fonction de son titre dans la bibliothèque. La méthode doit renvoyer null dans le cas où aucun livre n'a le bon titre.

  5. Comment le compilateur compile-t-il une boucle foreach sur une collection ?
    Utiliser la commande javap pour vérifier !
           javap -c Library.class
         

  6. Expliquer pourquoi la méthode findByTitle doit renvoyer null plutôt que de lever une exception.

  7. Écrire une méthode toString affichant les livres de la bibliothèque dans l'ordre d'insertion, avec les livres séparés par une virgule (avec un espace après la virgule).

Exercice 3 - Librarie 2 (le retour de la vengeance)

L'implantation faite dans l'exercice précédent est lente si la méthode findByTitle est appelée fréquemment. On va changer l'implantation en gardant la même API, c'est-à-dire avec les mêmes méthodes publiques (ayant les mêmes signatures). De cette façon, il ne sera pas nécessaire de changer le code du main !

  1. Quelle est la complexité de la méthode findByTitle de la classe Library ?

  2. Regarder la javadoc de la classe java.util.HashMap ainsi que celle de ses méthodes put et get.
    Quelle est la structure de données algorithmique dont java.util.HashMap est une implantation ?
    On veut améliorer la performance de la méthode findByTitle. On se propose d'utiliser la classe java.util.HashMap pour cela. Comment doit-on faire ?
    Quelle sera alors la complexité de findByTitle ?

  3. Commenter entièrement le code de la classe Library (pour ne pas perdre votre travail) et recopier les signatures des méthodes commentées. Pour l'instant, laisser la méthode toString de côté. Modifier les champs afin d'utiliser une java.util.HashMap et implanter le constructeur et les méthodes add et findByTitle.

  4. Expliquer pourquoi, ici, on a préféré utiliser une classe pour représenter Library plutôt qu'un record.

  5. Pour l'implantation de la méthode toString, quelle méthode de java.util.HashMap doit-on utiliser pour obtenir l'ensemble des valeurs stockées ? Si vous ne savez pas, lisez la javadoc !
    Écrire la méthode toString.

  6. En fait, la méthode toString ne fait pas exactement ce qui est demandé, car elle ne permet pas d'afficher les éléments dans l'ordre d'insertion. Sachant qu'il existe une classe LinkedHashMap, comment peut-on résoudre ce problème ?

  7. On souhaite ajouter une méthode removeAllBooksFromAuthor qui prend un nom d'auteur en paramètre et supprime tous les livres de cet auteur de la bibliothèque.
    Voici un exemple d'utilisation
           var library2 = new Library();
           library2.add(new Book("Da Vinci Code", "Dan Brown"));
           library2.add(new Book("Angels & Demons", "Dan Brown"));
           library2.removeAllBooksFromAuthor("Dan Brown");
         

    Sachant qu'il existe une méthode remove dans la classe java.util.HashMap, un étudiant qui n'a pas bien suivi le cours propose le code suivant
          public void removeAllBooksFromAuthor(String author) {
            for(var book: books.values()) {
              if (book.author().equals(author)) {
                books.remove(book.title());
              }
            }
          }
         

    Lorsque l'on exécute l'exemple, le code plante avec une exception.
    Quelle est l'exception levée et pourquoi ?

  8. En fait, il existe une méthode remove dans l'interface Iterator qui n'a pas ce problème, car le parcours et la suppression se font sur le même itérateur.
    Implanter correctement la méthode removeAllBooksFromAuthor.

  9. Quelle est la complexité pire cas du code que vous avez écrit ?

  10. [Revision] Pour les plus balèzes, sachant qu'il existe une méthode removeIf sur Collection, modifier le code de la méthode removeAllBooksFromAuthor.
    Note: le code devrait s'écrire en une ligne !