:: Enseignements :: ESIPE :: E3INFO :: 2016-2017 :: Programmation Objet avec Java ::
[LOGO]

Listes, tris, lambda et révisions


Exercice 1 - Listes de trucs... et comparateur de machins

  1. Considérez le bout de code suivant (à coller dans le main d'une classe fr.upem.lists.Test):
            List<String> list = new LinkedList<>();
            list.add("zero");
            list.add("one");
            list.add("two");
            list.add("three");
            list.add("four");
            list.add("five");
            list.add("six");
            list.add("seven");
            list.add("eight");
    
            // Why this loop sucks?
            for(int i=0; i<list.size(); i++) {
                System.out.println(list.get(i));
            }
            
            // Why this loop fails?
            for(String msg : list) {
                if(msg.equals("two")) {
                    list.remove("two");
                }
            }
     
    Pourquoi la première boucle est-elle une horreur? Quelle est sa complexité en taille de la liste? Écrivez-en une version linéaire.
    Pourquoi la seconde boucle provoque-t-elle une exception?
    Qu'est ce qu'un itérateur fail-fast?
    Comment pourrait-on écrire cette boucle pour qu'elle retire de la liste toutes les occurrences de "two"?
  2. L'interface java.util.List<E> définit une méthode de tri des éléments de cette liste et en fournit une implémentation par défaut default void sort(Comparator<? super E> c) à base d'un merge sort sur un tableau contenant tous les éléments de la liste.
    L'argument c de cette méthode est un comparateur implémentant l'interface java.util.Comparator pour un type paramètre qui soit un super-type de E: cela signifie qu'il suffit de disposer d'un comparateur entre éléments d'un super-type de E pour trier une liste de E.
    Par exemple, pour trier notre liste de String, il suffit de disposer d'un comparateur de java.lang.CharSequence, qui implémente la méthode public int compare(CharSequence cs1, CharSequence cs2).
    Écrivez une telle classe CharSequenceLengthComparator afin que le code suivant fonctionne à la fin de votre méthode main de la classe Test:
    Comparator<? super String> c = new CharSequenceLengthComparator(); 
    list.sort(c);
    System.out.println(list);
    
  3. En fait, java.util.Comparator<T> est une Functional Interface, c'est à dire qu'elle n'a qu'une seule méthode abstraite déclarée. Du coup, une lambda expression pourrait être utilisée comme argument de l'appel à list.sort(); sans déclarer de variable c et surtout sans avoir besoin de créer la classe CharSequenceLengthComparator, simplement en décrivant comment on compare deux éléments: réécrivez l'appel à list.sort(); en utilisant une lambda.
  4. Que ce passe-t-il si vous appelez list.sort(null);?

Exercice 2 - Panier éléctronique

Voici le code du package fr.umlv.shopping permettant de modéliser des livres numériques (avec un titre, un auteur et un prix) ainsi qu'un panier électronique dans lequel on peut ajouter ou retirer des livres. Il est possible d'afficher le panier et de calculer son prix. Les tests sont dans le package fr.umlv.shopping.test.

La boutique qui vend les livres se diversifie et vend désormais d'autres types de contenu numérique: des jeux-vidéo et des cartes cadeau dont on vous fournit le code.
Les jeux vidéo ont un titre, un type de console et un prix. Les cartes cadeau ont une valeur (entière) et une durée de validité en semaines. Leur prix est calculé en fonction de ces 2 paramètres.

Le but de l'exercice est de transformer le code fourni pour que l'on puisse également ajouter ces nouveaux types de contenu au panier. Et en réalité, la boutique prévoit déjà de vendre de la musique et des films à l'avenir (dans un format qui reste à définir), on aimerait donc que l'ajout de nouveaux média se fasse aisément par la suite.

  1. Modifier le code fourni pour que l'on puisse ajouter/retirer aussi bien des livres que des jeux vidéos et des cartes cadeau au panier.
  2. Vérifier que la suppression fonctionne bien dans tous les cas.
  3. Faire en sorte de minimiser la duplication de code.

Exercice 3 - Le compte est bon

Le but de cet exercice est de découvrir comment utiliser des lambdas et des streams.

  1. On cherche à compter le nombre d'occurences d'un mot dans une liste.
         List<String> list = Arrays.asList("hello", "world", "hello", "lambda");
         System.out.println(count(list, "hello"));
        
    Écrire le code de la méthode count sachant que le compteur est un entier long.
  2. On cherche à écrire une méthode count2 sémantiquement équivalente (qui fait la même chose) à count mais en utilisant l'API des Stream.
    Comment obtenir un Stream à partir d'un objet de type List ?
    L'idée, ici, est de filtrer le stream pour ne garder que les mots égaux au mot passé en paramètre puis de compter ceux-ci.
    Quel sont les méthodes permettant respectivement de filtrer un stream et de compter le nombre d’éléments ?
    La méthode qui permet de filtrer prend un objet de type Predicate<T> en paramètre. Dans notre cas, quel est le type correspondant à T ?
    Indiquer le code permettant de créer une lambda filtrant sur le mot passé en paramètre que l'on peut déclarer en tant que Predicate
    Écrire le code de la méthode count2.