On cherche à réimplanter l'API des Stream (juste pour le fun),
comme l'API est assez complexe, on ne réimplantera qu'une sous-partie.
Pour cela, nous allons définir une interface
Pour ce TP, nous allons utiliser la même configuration Maven qu'habituellement.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.uge.query</groupId>
<artifactId>query</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>21</release>
<compilerArgs>
<compilerArg>--enable-preview</compilerArg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
</plugins>
</build>
</project>
Comme précédemment, créer un projet Maven,
au niveau du premier écran, cocher
create simple project
puis passer à l'écran suivant en indiquant
Next.
On peut remarquer que les preview features sont activés, ce qui nous aidera pour
la dernière question du TP.
Pour ce TP, le groupId est
fr.uge.query , l'artefactId est
query et
la version est
0.0.1-SNAPSHOT. Puis cliquer sur
Finish.
Une
Query est une réimplantation simple d'une partie de l'API des
Stream.
C'est une interface que l'on crée à partir d'une liste ou d'un
iterable,
qui agit comme une
vue et qui possède les traditionnelles méthodes
filter,
map et
reduce.
Comme pour l'API des
Stream, ces méthodes n'effectuent pas le calcul tant qu'une opération terminale
comme
toString,
toList ou
reduce n'est pas exécutée.
L'interface
Query possède une seule implantation
QueryImpl qui
sera définie en tant que classe interne de l'interface
Query.
La classe
QueryImpl est la seule implantation possible de
Query.
Il existe deux méthodes pour créer une
Query, la méthode
fromList et la méthode
fromIterable. La méthode
fromList, en plus de prendre en paramètre une liste, prend
comme second paramètre une fonction qui indique si chaque élément de la liste doit ou non être présent
lors d'un calcul sur la
Query (en utilisant un
Optional).
Par exemple, si l'on veut créer une
Query de noms à partir d'une liste d'animaux de compagnie
(
Pet) qui peuvent posséder un nom, on va écrire le code suivant :
record Pet(Optional<String> name) { }
List<Pet> pets = List.of(new Pet(Optional.of("Scooby"), new Pet(Optional.empty())));
Query<String> query = Query.fromList(pets, Pet::name);
System.out.println(query); // Scooby
Le record
Pet indique si le nom de l'animal existe ou non grâce à un
Optional.
La
Query est créé en indiquant que seul les noms des animaux de la liste qui ont un nom
(ceux dont l'
Optional est présent) sont à prendre en compte.
La méthode
fromIterable permet de créer une
Query directement depuis
un
Iterable, par exemple
List<Integer> list = List.of(1, 2, 4, 8);
Query<Integer> query = Query.fromIterable(list);
L'interface
Query possède les méthodes :
-
toList qui calcule les éléments d'une Query et les ajoute à une liste
(non-modifiable une fois renvoyée),
-
toStream qui renvoie la liste sous-forme de Stream, dans ce cas
les calculs ne sont faits que lorsque qu'une opération terminale est appelée sur le Stream,
-
toLazyList qui renvoie une liste non-modifiable dont la taille et les éléments sont calculés uniquement
si on demande cette information (lazy veut dire paresseux en Anglais),
-
et les méthodes classiques filter, map et reduce.