:: Enseignements :: Licence :: L3 :: 2021-2022 :: Programmation Objet avec Java ::
[LOGO]

Lambda, interface fonctionnelle et type fonction


Exercice 1 - upperCaseAll

On souhaite écrire, dans une classe Lambdas, une méthode statique upperCaseAll qui prend en paramètre une liste de chaînes de caractères et met chaque chaîne en majusucules.

  1. Rappeler comment on met une chaîne de caractères en majusucules, indépendamment de la langue dans laquelle l'OS est configuré.
  2. On va utiliser la méthode List.replaceAll pour mettre toutes les chaînes de caractères en majuscules. Quelle est l'interface fonctionnelle utilisée par la méthode replaceAll ?
  3. À quel type de fonction cela correspond-il ? Autrement dit, que prend la fonction en argument et que renvoie-t-elle ?)
  4. Sachant que l'on appelle replaceAll avec une liste de String, quel est le type des paramètres de la lambda et quel est son type de retour ?
  5. Écrire le code de la méthode upperCaseAll

Exercice 2 - occurences

On souhaite calculer le nombre d'occurences de chaque chaîne de caractères dans une liste de chaînes de caractères. Par exemple, avec la liste ["foo", "bar", "foo"], la méthode occurences va renvoyer {"foo" = 2, "bar" = 1}.

  1. Quelle est le type du paramètre de la méthode occurences ?
    Quelle est le type de retour de la méthode occurences ?
  2. Quelle est l'implantation que l'on doit choisir ici ?
  3. On veut parcourir la liste avec la méthode forEach. Quelle interface fonctionnelle prend-elle en paramètre ? Quel est le type fonction correspondant ? Ici, quels sont les types des paramètres / de retour de la lambda que vous allez utliser ?
  4. Pour compter le nombre d'occurences, on va utiiser la méthode merge de la structure de données que vous avez choisi de renvoyer. Quelle interface fonctionnelle prend-elle en paramètre ? Quel est le type fonction correspondant ? Ici, quels sont les types des paramètres / de retour de la lambda que vous allez utliser ?
  5. Écrire le code de occurences, toujours dans la classe Lambdas.
  6. On peut noter qu'il existe une méthode statique sum dans la classe java.lang.Integer qui fait la somme de deux valeurs, on peut donc l'utiliser sous forme de method reference à la place de la lambda, lors de l'appel à merge. Modifier le code pour l’utiliser (garder la précédente version en commentaires).
  7. On peut se rendre compte que la méthode occurences fonctionne avec des listes de n'importe quel type, et pas uniquement des String. Modifier la signature de la méthode pour qu'elle marche avec n'importe quel type.

Exercice 3 - groupBy

On souhaite pouvoir grouper des acteurs par leurs prénoms (firstName), avec les acteurs définis ainsi :
     public record Actor(String firstName, String lastName) {
       public Actor {
         Objects.requireNonNull(firstName);
         Objects.requireNonNull(lastName);
       }
     }
    
On va pour cela écrire une méthode actorGroupByFirstName qui prend en paramètre une liste d'acteurs, par exemple [Actor("bob", "de niro"), Actor("willy", "cat"), Actor("bob", "cat")] et renvoie une Map qui, pour un prénom, contient une liste de tous les acteurs ayant ce prénom. Avec notre exemple de liste, cela donne :
     {
       "bob" = [Actor("bob", "de niro"), Actor("bob", "cat")],
       "willy" = [Actor("willy", "cat")]
     }
    

  1. Quel est le type de paramètre de actorGroupByFirstName ? Quel est le type de retour de actorGroupByFirstName ?
  2. Rappeler comment marche la méthode Map.computeIfAbsent. Son second paramètre est une interface fonctionnelle, à quel type de fonction correspond-elle ? Expliquer à quoi correspondent le premier paramètre et le second paramètre de Map.computeIfAbsent, puis comment on peut l'utiliser pour grouper les acteurs selon leur prénom.
  3. Dans notre cas, quel doit être le type de la lambda passée en second paramètre de computeIfAbsent ?
  4. Écrire la méthode actorGroupByFirstName()
  5. Si on veut maintenant grouper les acteurs par rapport à leur nom (lastName) au lieu du prénom, on va écrire à peu près le même code. On veut généraliser le code en écrivant une méthode actorGroupBy. qui prend en paramètre une liste d'acteurs ainsi qu'une fonction qui, étant donné un acteur, renvoie la valeur par laquelle il va être groupé. Et elle renvoie une Map des valeur par lesquelles on les groupe, associées aux listes d'acteurs groupés.
    Par exemple, on va écrire :
           var group1 = actorGroupBy(actors, Actor::firstName)  // groupe par prénom
           var group2 = actorGroupBy(actors, Actor::lastName)   // groupe par nom
         

    Quelle doit être le type fonction du second paramètre de actorGroupBy ?
    Quelle est l'interface fonctionnelle correspondante ?
    Quelle doit être le type du second paramètre de actorGroupBy ?
    Écrire la méthode actorGroupBy.
  6. Ici aussi, on peut généraliser pour que la méthode ne fonctionne pas uniquement avec des acteurs, mais avec n'importe quel type.
    Écrire la méthode groupBy qui prend en paramètre n'importe quel type de liste et n'importe quelle fonction.
    Note : ici, on a besoin de deux paramètres de type : T qui est l'équivalent de Actor et U qui est l'équivalent de String, afin que cela fonctionne aussi si la clé pour grouper n'est pas de type String (par exemple, un autre type de composant du record).