Dans mon précédent billet sur le développement de plugin pour Confluence, j’ai évoqué le style de programmation fonctionnelle sans entrer dans le détail. Nous allons ici rentrer un peu plus dans le détail avec une petite introduction à l’API GoogleCollections (packagée maintenant dans Guava).
La programmation orientée objet use de la mutabilité pour décrire un programme (machine à état) alors que la programmation fonctionnelle le décrit comme un enchainement de fonctions. Cela a pour avantage d’éviter les effets de bords dus aux changements d’états : on écrit du code plus déterministe. Java n’est pas un langage fonctionnel a proprement parler mais cette API lui donne une touche fonctionnelle à laquelle prendra goût tout développeur Java perfectionniste. Elle est simple, concise et satisfaisante en terme de productivité. Ce n’est pas nouveau me direz-vous mais c’est toujours intéressant, ne serait-ce que pour la culture.
Vous pouvez l’ajouter dans votre projet Maven avec ces coordonnées :
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>r09</version> </dependency>
Elle embarque tout un tas de méthodes statiques pour initialiser des collections :
List list = newArrayList(); Map map = newHashMap();
C’est peu de chose certes, mais c’est toujours mieux que d’initialiser à la main.
Pour appliquer une fonction de transformation sur une liste, par exemple pour transformer une liste d’un objet du modèle en un autre :
@Test public void testBidon() { List nodes = newArrayList(new Node("a"),new Node("b"),new Node("c")); List nodesDTO = Lists.transform(nodes, new Function(){ public NodeRepresentation apply(@Nullable Node from) { return new NodeRepresentation(from); } }); assertThat(nodesDTO).hasSize(3); }
Pour rechercher un élément dans une liste :
@Test public void find() { List allNodes = newArrayList(new Node("a"), new Node("b"), new Node("c")); Node specialNode = Iterables.find(allNodes, new Predicate() { public boolean apply(Node n) { return n.getName().equals("b"); } }); assertThat(allNodes.get(1)).equals(specialNode); }
Filter une liste d’items :
@Test public void filter() { List allNodes = newArrayList(new Node(3,4), new Node(10,11), new Node(1,2)); Iterable someSpecialNodes = Iterables.filter(allNodes, new Predicate() { public boolean apply(Node n) { return Math.sqrt(Math.pow(n.getX(), 2) + Math.pow(n.getY(), 2)) >= 10; } }); assertThat(someSpecialNodes).hasSize(1); }
Ou encore quelquechose qui n’a rien à voir avec du style fonctionnel mais qui peut servir quand même : l’utilisation de Joiner :
@Test public void join() { List locales = newArrayList(new Locale("fr"), null, new Locale("en")); String res = Joiner.on(',').skipNulls().join(locales); assertThat(res).isEqualToIgnoringCase("fr,en"); }
J’en passe et des meilleurs : ordonnancement et difference sur des collections… La documentation est riche et il y a plein d’exemples sur le net.
Si vous ne connaissiez pas c’est le moment de regarder et d’embrasser le style fonctionnel. Guava embarque aussi tout un tas d’utilitaires pour les entrées/sorties, la concurrence, les primitives et bien d’autres choses utiles.
[…] précédent article parlait de teinter la programmation Java d’un petit style fonctionnel avec la librairie […]