1. Innovations en Java 8 : programmation fonctionnelle

Avec la sortie de Java 8, le langage a acquis un support puissant pour la programmation fonctionnelle . On pourrait même dire qu'il a obtenu un support tant attendu pour la programmation fonctionnelle. Le codage est devenu plus rapide, même si le code était plus difficile à lire 🙂

Avant d'apprendre la programmation fonctionnelle en Java, nous vous recommandons de bien comprendre trois choses :

  1. POO, héritage et interfaces ( Niveaux 1-2 dans la quête Java Core ).
  2. Implémentations de méthode par défaut dans une interface .
  3. Classes internes et anonymes .

La bonne nouvelle est que vous n'avez pas besoin de connaître tout cela pour utiliser de nombreuses fonctionnalités de la programmation fonctionnelle en Java. La mauvaise nouvelle est qu'il sera difficile de comprendre exactement comment tout est arrangé et comment tout fonctionne sans connaître les classes internes anonymes.

Dans les leçons à venir, nous nous concentrerons sur la facilité et la simplicité d'utilisation des fonctionnalités de programmation fonctionnelle de Java, sans une compréhension approfondie de son fonctionnement.

Il faut des mois pour comprendre toutes les nuances de la programmation fonctionnelle en Java. Vous pouvez apprendre à lire un tel code en quelques heures. Nous vous suggérons donc de commencer petit. Même si c'est avec des flux d'E/S.


2. Flux d'E/S : pipelines de flux

Vous souvenez-vous qu'il était une fois que vous avez entendu parler des flux d'E/S : InputStream, OutputStream, Reader, Writeretc. ?

Certaines classes de flux lisent des données à partir de sources de données , telles que FileInputSteam, et des flux de données intermédiaires lisent des données à partir d'autres flux, tels que InputStreamReaderet BufferedReader.

Ces flux pourraient être organisés en pipelines de traitement de données. Par exemple, comme ceci :

FileInputStream input = new FileInputStream("c:\\readme.txt");
InputStreamReader reader = new InputStreamReader(input);
BufferedReader buff = new BufferedReader(reader);

String text = buff.readLine();

Il est important de noter que dans les premières lignes de code, nous construisons simplement une chaîne d' Streamobjets. Les données n'ont pas encore transité par le pipeline.

Mais dès que nous appelons la buff.readLine()méthode, ce qui suit se produit :

  1. L' BufferedReaderobjet appelle la read()méthode sur l' InputStreamReaderobjet
  2. L' InputStreamReaderobjet appelle la read()méthode sur l' FileInputStreamobjet
  3. L' FileInputStreamobjet commence à lire les données du fichier

En d'autres termes, il n'y a aucun mouvement de données le long du pipeline de flux jusqu'à ce que nous commencions à appeler des méthodes telles que read()ou readLine(). La simple construction du pipeline de flux ne fait pas passer les données à travers celui-ci. Les flux eux-mêmes ne stockent pas de données. Ils ne lisent que les autres.

Collections et flux

À partir de Java 8, il est devenu possible d'obtenir un flux pour lire les données des collections (et pas seulement d'elles). Mais ce n'est pas le plus intéressant. Il est en effet devenu possible de construire facilement et simplement des chaînes complexes de flux de données. Et ce faisant, le code qui prenait auparavant 5 à 10 lignes pouvait désormais être écrit en 1 à 2 lignes.

Exemple de recherche de la chaîne la plus longue dans une liste de chaînes :

Trouver la chaîne la plus longue
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String max = list.stream().max((s1, s2)-> s1.length()-s2.length()).get();
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
Stream<String> stream = list.stream();
Optional<String> optional = stream.max((s1, s2)-> s1.length()-s2.length());
String max = optional.get();

3. Streaminterfaces

La prise en charge étendue de Java 8 pour les flux est implémentée à l'aide de l' Stream<T>interface, où Test un paramètre de type qui indique le type de données transmises dans le flux. En d'autres termes, un flux est totalement indépendant du type de données qu'il transmet.

Pour obtenir un objet stream à partir d'une collection , appelez simplement sa stream()méthode. Le code ressemble à peu près à ceci :

Stream<Type> name = collection.stream();
Obtenir un flux à partir d'une collection

Dans ce cas, la collection sera considérée comme la source de données du flux et l' Stream<Type>objet sera un outil permettant d'obtenir des données de la collection sous la forme d'un flux de données.

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
Stream<String> stream = list.stream();

Au fait, vous pouvez obtenir un flux non seulement à partir de collections, mais également à partir de tableaux . Pour ce faire, vous devez utiliser la méthode. Par exemple:Arrays.stream()

Stream<Type> name = Arrays.stream(array);
Obtenir un flux à partir d'un tableau

Dans ce cas, le tableau sera considéré comme la source de données du flux appelé name.

Integer[] array = {1, 2, 3};
Stream<Integer> stream = Arrays.stream(array);

Aucune donnée n'est déplacée lors Stream<Type>de la création de l'objet. Nous avons simplement obtenu un objet de flux afin de commencer à construire un pipeline de flux.