Java 8 - Flux
Stream est une nouvelle couche abstraite introduite dans Java 8. En utilisant Stream, vous pouvez traiter les données de manière déclarative similaire aux instructions SQL. Par exemple, considérez l'instruction SQL suivante.
SELECT max(salary), employee_id, employee_name FROM Employee
L'expression SQL ci-dessus renvoie automatiquement les détails de l'employé salarié maximum, sans effectuer de calcul du côté du développeur. En utilisant le framework de collections en Java, un développeur doit utiliser des boucles et effectuer des vérifications répétées. Une autre préoccupation est l'efficacité; comme les processeurs multicœurs sont facilement disponibles, un développeur Java doit écrire un traitement de code parallèle qui peut être assez sujet aux erreurs.
Pour résoudre ces problèmes, Java 8 a introduit le concept de flux qui permet au développeur de traiter les données de manière déclarative et de tirer parti de l'architecture multicœur sans avoir à écrire de code spécifique pour celle-ci.
Qu'est-ce que le flux ?
Stream représente une séquence d'objets à partir d'une source, qui prend en charge les opérations d'agrégation. Voici les caractéristiques d'un Stream −
-
Séquence d'éléments − Un flux fournit un ensemble d'éléments d'un type spécifique de manière séquentielle. Un flux obtient/calcule des éléments à la demande. Il ne stocke jamais les éléments.
-
Source − Stream prend des collections, des tableaux ou des ressources d'E/S comme source d'entrée.
-
Opérations agrégées − Stream prend en charge les opérations agrégées telles que filtrer, mapper, limiter, réduire, rechercher, faire correspondre, etc.
-
Pipeline − La plupart des opérations de flux renvoient le flux lui-même afin que leur résultat puisse être pipeliné. Ces opérations sont appelées opérations intermédiaires et leur fonction est de prendre des entrées, de les traiter et de renvoyer la sortie à la cible. La méthode collect() est une opération terminale qui est normalement présente à la fin de l'opération de pipelining pour marquer la fin du flux.
-
Itérations automatiques − Les opérations de flux effectuent les itérations en interne sur les éléments source fournis, contrairement aux collections où une itération explicite est requise.
Générer des flux
Avec Java 8, l'interface Collection dispose de deux méthodes pour générer un flux.
-
flux() − Renvoie un flux séquentiel en considérant la collection comme sa source.
-
flux parallèle() − Renvoie un Stream parallèle en considérant la collection comme sa source.
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
pour chaque
Stream a fourni une nouvelle méthode ‘forEach’ pour itérer chaque élément du flux. Le segment de code suivant montre comment imprimer 10 nombres aléatoires à l'aide de forEach.
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
carte
La méthode ‘map’ est utilisée pour mapper chaque élément à son résultat correspondant. Le segment de code suivant imprime des carrés uniques de nombres à l'aide de map.
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of unique squares List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
filtrer
La méthode « filtre » est utilisée pour éliminer des éléments en fonction d'un critère. Le segment de code suivant imprime un nombre de chaînes vides à l'aide du filtre.
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.stream().filter(string -> string.isEmpty()).count();
limite
La méthode ‘limit’ est utilisée pour réduire la taille du flux. Le segment de code suivant montre comment imprimer 10 nombres aléatoires en utilisant limit.
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
trié
La méthode ‘sorted’ est utilisée pour trier le flux. Le segment de code suivant montre comment imprimer 10 nombres aléatoires dans un ordre trié.
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
Traitement parallèle
parallelStream est l'alternative de stream pour le traitement parallèle. Jetez un œil au segment de code suivant qui imprime un nombre de chaînes vides à l'aide de parallelStream.
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
Il est très facile de basculer entre les flux séquentiels et parallèles.
Collectionneurs
Les collecteurs permettent de combiner le résultat d'un traitement sur les éléments d'un flux. Les collecteurs peuvent être utilisés pour renvoyer une liste ou une chaîne.
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered List: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString);
Statistiques
Avec Java 8, des collecteurs de statistiques sont introduits pour calculer toutes les statistiques lorsque le traitement de flux est en cours.
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Highest number in List : " + stats.getMax()); System.out.println("Lowest number in List : " + stats.getMin()); System.out.println("Sum of all numbers : " + stats.getSum()); System.out.println("Average of all numbers : " + stats.getAverage());
Exemple de flux
Créez le programme Java suivant à l'aide de l'éditeur de votre choix dans, par exemple, C:\> JAVA.
Java8Tester.java
Démo en directimport java.util.ArrayList; import java.util.Arrays; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Random; import java.util.stream.Collectors; import java.util.Map; public class Java8Tester { public static void main(String args[]) { System.out.println("Using Java 7: "); // Count empty strings List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); System.out.println("List: " +strings); long count = getCountEmptyStringUsingJava7(strings); System.out.println("Empty Strings: " + count); count = getCountLength3UsingJava7(strings); System.out.println("Strings of length 3: " + count); //Eliminate empty string List<String> filtered = deleteEmptyStringsUsingJava7(strings); System.out.println("Filtered List: " + filtered); //Eliminate empty string and join using comma. String mergedString = getMergedStringUsingJava7(strings,", "); System.out.println("Merged String: " + mergedString); List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of square of distinct numbers List<Integer> squaresList = getSquares(numbers); System.out.println("Squares List: " + squaresList); List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19); System.out.println("List: " +integers); System.out.println("Highest number in List : " + getMax(integers)); System.out.println("Lowest number in List : " + getMin(integers)); System.out.println("Sum of all numbers : " + getSum(integers)); System.out.println("Average of all numbers : " + getAverage(integers)); System.out.println("Random Numbers: "); //print ten random numbers Random random = new Random(); for(int i = 0; i < 10; i++) { System.out.println(random.nextInt()); } System.out.println("Using Java 8: "); System.out.println("List: " +strings); count = strings.stream().filter(string->string.isEmpty()).count(); System.out.println("Empty Strings: " + count); count = strings.stream().filter(string -> string.length() == 3).count(); System.out.println("Strings of length 3: " + count); filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered List: " + filtered); mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString); squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList()); System.out.println("Squares List: " + squaresList); System.out.println("List: " +integers); IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics(); System.out.println("Highest number in List : " + stats.getMax()); System.out.println("Lowest number in List : " + stats.getMin()); System.out.println("Sum of all numbers : " + stats.getSum()); System.out.println("Average of all numbers : " + stats.getAverage()); System.out.println("Random Numbers: "); random.ints().limit(10).sorted().forEach(System.out::println); //parallel processing count = strings.parallelStream().filter(string -> string.isEmpty()).count(); System.out.println("Empty Strings: " + count); } private static int getCountEmptyStringUsingJava7(List<String> strings) { int count = 0; for(String string: strings) { if(string.isEmpty()) { count++; } } return count; } private static int getCountLength3UsingJava7(List<String> strings) { int count = 0; for(String string: strings) { if(string.length() == 3) { count++; } } return count; } private static List<String> deleteEmptyStringsUsingJava7(List<String> strings) { List<String> filteredList = new ArrayList<String>(); for(String string: strings) { if(!string.isEmpty()) { filteredList.add(string); } } return filteredList; } private static String getMergedStringUsingJava7(List<String> strings, String separator) { StringBuilder stringBuilder = new StringBuilder(); for(String string: strings) { if(!string.isEmpty()) { stringBuilder.append(string); stringBuilder.append(separator); } } String mergedString = stringBuilder.toString(); return mergedString.substring(0, mergedString.length()-2); } private static List<Integer> getSquares(List<Integer> numbers) { List<Integer> squaresList = new ArrayList<Integer>(); for(Integer number: numbers) { Integer square = new Integer(number.intValue() * number.intValue()); if(!squaresList.contains(square)) { squaresList.add(square); } } return squaresList; } private static int getMax(List<Integer> numbers) { int max = numbers.get(0); for(int i = 1;i < numbers.size();i++) { Integer number = numbers.get(i); if(number.intValue() > max) { max = number.intValue(); } } return max; } private static int getMin(List<Integer> numbers) { int min = numbers.get(0); for(int i= 1;i < numbers.size();i++) { Integer number = numbers.get(i); if(number.intValue() < min) { min = number.intValue(); } } return min; } private static int getSum(List numbers) { int sum = (int)(numbers.get(0)); for(int i = 1;i < numbers.size();i++) { sum += (int)numbers.get(i); } return sum; } private static int getAverage(List<Integer> numbers) { return getSum(numbers) / numbers.size(); } }
Vérifier le résultat
Compilez la classe en utilisant javac compilateur comme suit −
C:\JAVA>javac Java8Tester.java
Exécutez maintenant le Java8Tester comme suit −
C:\JAVA>java Java8Tester
Cela devrait produire le résultat suivant −
Using Java 7: List: [abc, , bc, efg, abcd, , jkl] Empty Strings: 2 Strings of length 3: 3 Filtered List: [abc, bc, efg, abcd, jkl] Merged String: abc, bc, efg, abcd, jkl Squares List: [9, 4, 49, 25] List: [1, 2, 13, 4, 15, 6, 17, 8, 19] Highest number in List : 19 Lowest number in List : 1 Sum of all numbers : 85 Average of all numbers : 9 Random Numbers: -1279735475 903418352 -1133928044 -1571118911 628530462 18407523 -881538250 -718932165 270259229 421676854 Using Java 8: List: [abc, , bc, efg, abcd, , jkl] Empty Strings: 2 Strings of length 3: 3 Filtered List: [abc, bc, efg, abcd, jkl] Merged String: abc, bc, efg, abcd, jkl Squares List: [9, 4, 49, 25] List: [1, 2, 13, 4, 15, 6, 17, 8, 19] Highest number in List : 19 Lowest number in List : 1 Sum of all numbers : 85 Average of all numbers : 9.444444444444445 Random Numbers: -1009474951 -551240647 -2484714 181614550 933444268 1227850416 1579250773 1627454872 1683033687 1798939493 Empty Strings: 2
Java