Date de première publication : 2023/02/06
Notions : manipuluation des collections et streams
Exemples du cours
Voici comment créer une liste avec deux manières de l'afficher :
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// une liste est directement affichable
System.out.println(list);
// on peut appliquer une opération terminale
// l'action est donnée par une référence de méthode
list.stream().forEach(System.out::println);
// Creation d'un stream d'entiers :
IntStream.rangeClosed(1, 10);
// ou encore
Stream stream = Stream.iterate(1, n -> n + 1).limit(10);
Dans le dernier exemple, on convertit la liste en stream. On peut également faire l'inverse si nécessaire, on peut créer une liste à partir d'un stream (bon, là, y a pas d'intérêt, on a déjà la liste):
List l = list.stream().collect(Collectors.toList());
System.out.println(l);
On va maintenant trier les nombres pairs de plusieurs manières :
// avec une lambda
list.stream().filter(n -> n % 2 == 0);
// avec une inferface fonctionnelle
list.stream().filter(new Predicate() {
public boolean test(Integer i) {
return Integer.valueOf(i) % 2 == 0;
}
});
et la dernière en montrant l'interface fonctionnelle :
class Rien {
static public boolean isEven(Integer i) {
return Integer.valueOf(i) % 2 == 0;
}
}
list.stream().filter(Rien::isOdd);
Il n'est même pas nécessaire de préciser l'interface même si c'est une bonne pratique !
Dans le dernier exemple isEven()
est une méthode de classe, donc la référence de méthode est donnée
par rapport à la classe. Si la méthode est une méthode classique,
il faut la lier à une instance instance::methode
.
Application : exploitation de données
Nous allons reprendre l'exemple classique de la liste de créateurs de langages de programmation. Par exemple :
gosling:james:java:1995
stroustrup:bjarne:c++:1983
van rossum:guido:1991
hoare:graydon:rust:2006
Ces données peuvent être stockées dans des objets de type Personne
qui dispose des différents attributs nécessaires.
On veut faire différentes opérations sur les données :
- Lister les concepteurs de langages dans l'ordre lexicographique de leur nom
- Lister les concepteurs de langages dans l'ordre lexicographique de leur prénom
- Lister les langages dans l'ordre lexicographique de leur nom
- Lister les langages suivant l'année de création
- Calculer l'année moyenne de création des langages
La dernière chose que l'on va faire est de calculer l'année moyenne de création d'un langage. Vous pourrez à cet effet utiliser mapToInt()
pour transformer le stream objet en IntStream
puis appliquer des méthodes comme average()
, sum()
, count()
Lecture des données avec un Stream
On peut lire le fichier texte avec des méthodes "classiques" mais on peut également le faire avec un Stream
Stream<String> stream = Files.lines(Paths.get(nomDuFichier));
stream.forEach(System.out::println);
dans un try-with-resources
ou un try-catch
standard.
Le code fourni permet de lire un stream de chaines de caractères mais il est possible de créer un stream de Personne
Pour ce faire, il est possible d'associer une chaine de caractères et une personne avec map, ou bien encore d'analyser la chaine de caractères et de créer ensuite une personne :
La classeString
peut être remplacée par la classe Personne
et le stream transformé en collection grâce à la méthode collect()
pour éviter les lectures multiples.
// methode 1
stream.map(ligne -> ligne.split(":")).map(tableau -> new Personne(tableau[0], tableau[1], tableau[2], tableau[3]));
// methode 2
stream.map(ligne -> new Personne(ligne));
Vous choisirez une méthode et écrirez le constructeur qui va bien. Vous aurez également à définir la méthode toString()
pour avoir un affichage correct.
Exploitations des données
Pour ce faire, on vous propose d'utiliser un Stream et de donner de différentes manières le "comparateur". Pour rappel, voici quelques possibilités vues en cours :
La dernière chose que l'on va faire est de calculer l'année moyenne de création d'un langage.
Vous pourrez à cet effet utiliser :
mapToInt()
pour transformer le stream objet enIntStream
puis appliquer des méthodes commeaverage()
,sum()
,count()
- Un collector particulier et ensuite disposer de méthodes :
averagingInt()
,summingInt()
ou encoresummarizingInt()
. Le collecteur permet aussi de regroupe les éléments si besoin avecgroupBy