Java 8 - Flux
Stream est une nouvelle couche abstraite introduite dans Java 8. En utilisant stream, vous pouvez traiter les données d'une 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 aucun 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 d'exploiter l'architecture multicœur sans avoir besoin d'écrire de code spécifique pour celle-ci.
Qu'est-ce que Stream?
Stream représente une séquence d'objets provenant d'une source, qui prend en charge les opérations d'agrégation. Voici les caractéristiques d'un Stream -
Sequence of elements- Un flux fournit un ensemble d'éléments de type spécifique de manière séquentielle. Un flux récupère / 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.
Aggregate operations - Stream prend en charge les opérations agrégées telles que filtrer, mapper, limiter, réduire, rechercher, faire correspondre, etc.
Pipelining- 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.
Automatic iterations - 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 a deux méthodes pour générer un Stream.
stream() - Renvoie un flux séquentiel en considérant la collection comme sa source.
parallelStream() - 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 la carte.
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());
filtre
La méthode «filtre» permet d'éliminer des éléments en fonction d'un critère. Le segment de code suivant imprime un nombre de chaînes vides à l'aide de filter.
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 «limite» est utilisée pour réduire la taille du flux. Le segment de code suivant montre comment imprimer 10 nombres aléatoires à l'aide de limit.
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
trié
La méthode «triée» 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 sont utilisés pour combiner le résultat du 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 du 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 en utilisant n'importe quel éditeur de votre choix dans, par exemple, C: \> JAVA.
Java8Tester.java
import 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érifiez 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
Il 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