Étiquette : Java Streams

Vincent Lecomte
[Java] Mémo – Trucs et astuces impliquant l’API Stream

[Java] Mémo – Trucs et astuces impliquant l’API Stream

Java propose l’API Stream, qui permet de manipuler et effectuer des opérations sur un ensemble de données, telles qu’une collection, un tableau ou même un flux I/O. Elle offre diverses possibilités : tri, parcours de collections, extraction d’éléments à l’aide de filtres, etc.

Dans cet article nous allons voir comment effectuer un tri basique pour retourner une nouvelle liste mais également comment retourner une liste d’objets d’un type spécifique.

Trier une liste

On suppose que l’opération sera effectuée sur une liste d’objets de la classe Client. Cette dernière définit plusieurs membres dont un numéro de client (numClient) et son getter. Nous souhaitons récupérer une nouvelle liste de noms.

listeClients.stream()
	.sorted(Comparator.comparing(Client::getNumClient))
	.map(lo_c -> lo_c.getNomClient())
	.collect(Collectors.toList());

Dans cet exemple nous avons effectué plusieurs opérations sur le stream :

  • Une opération intermédiaire de tri, grâce à la méthode sorted() qui reçoit en paramètre un Comparator.
  • Une seconde opération intermédiaire qui permet de définir ce que l’on souhaite récupérer, en l’occurrence le nom de la personne.
  • Une troisième opération, finale cette fois, qui consiste en une réduction: on demande à ce que le résultat soit sous forme de liste.

Notez que si vous manipulez une List vous pouvez la trier directement à l’aide de la méthode sort(). La méthode effectue l’opération sur la liste existante sans en créer une copie de celle-ci.

Exemple:

listeClients.sort(Comparator.comparing(Client::getNumClient));

Retourner une liste d’un type spécifique

Comme on l’a vu ci-dessus, à l’aide de la méthode map(), on a obtenu une liste de chaines de caractères. Voyons comment aller plus loin pour retourner une liste d’un type spécifique. Toujours sur base d’un client, nous avons une classe nommée ClientDTO qui sera une version réduite. Elle contiendra uniquement le numéro de client et son nom, ainsi qu’un constructeur prenant en paramètre ces deux champs.

listeClients.stream()
	.sorted(Comparator.comparing(Client::getNumClient))
	.collect(Collectors.mapping(lo_c -> {
		return new ClientDTO(
			lo_c.getNumClient(), lo_c.getNomClient()
		);
	}, Collectors.toList()));

Cette fois on effectue un mappage à l’aide de Collectors.mapping(): la fonction en paramètre retourne une instance de ClientDTO avec les champs de notre classe Client. On demande ensuite à ce que le résultat final soit retourné sous forme de liste, comme dans l’exemple ci-dessus.

Bien sûr ce sont deux exemples parmi tant d’autres, l’API offrant énormément de possibilités. Et même si cela a été introduit dans Java 8 on n’a pas toujours la possibilité ou le temps d’en explorer les différentes méthodes. Voici quelques liens qui pourraient vous intéresser pour creuser le sujet:

Bon développement !

[Java] Filtre sur liste avec les streams

[Java] Filtre sur liste avec les streams

L’une des grosses améliorations de Java 8, c’est ce qu’on appelle les streams. C’est un nouveau pattern de manipulation de données et cela permet de se passer notamment des itérateurs que l’on connait. On peut les utiliser sur des collections ou même des tableaux.

On prend la classe suivante comme exemple :

public class MyObject
{
 private String sId;
 private String sName;
 
 // ...
}

Une méthode nous retourne alors une liste qui reprend des objets caractérisés par leur nom et un identifiant. On voudrait filtrer la liste pour ne récupérer que les objets nommés “chair” par exemple.

Stream<MyObject> lo_s = lo_listObj.stream().filter(
 myObj -> myObj.getName().equals("chair")
);

Le paramètre de la méthode filter() est un prédicat (type Predicate). Le code ci-dessus renvoie un stream que l’on peut ensuite manipuler pour retourner une collection ou bien un seul objet. Par exemple on pourrait utiliser la méthode collect() pour renvoyer une nouvelle liste.

List<Myobject> lo_list = lo_s.collect(Collectors.toList());

On peut aussi retourner le premier objet qui correspond au filtre, avec findFirst(). Cela retourne un objet de type Optional.

Optional<MyObject> lo_opt = lo_s.findFirst();

Plusieurs opérations sont possibles sur cet objet. On peut savoir s’il y a bien un résultat avec la méthode isPresent(), ou bien retourner directement le résultat ou une autre valeur si aucun objet n’avait été trouvé lors du filtre.

MyObject lo_result = lo_opt.orElse(lo_defaultObject);

La méthode orElse() renvoie la valeur qui avait été trouvée et si elle n’est pas présente, alors elle renvoie un autre objet du même type.

if (lo_opt.isPresent())
{
 MyObject lo_result = lo_opt.get();
}

L’exemple ci-dessus montre comment récupérer l’objet uniquement s’il est présent et pour également éviter l’exception NoSuchElementException. Cela peut être un raccourci à la méthode orElse(), tout dépend de quoi on a besoin en retour et ce qu’on va en faire.