Java 8 - Flujos
Stream es una nueva capa abstracta introducida en Java 8. Usando stream, puede procesar datos de una manera declarativa similar a las declaraciones SQL. Por ejemplo, considere la siguiente instrucción SQL.
SELECT max(salary), employee_id, employee_name FROM Employee
La expresión SQL anterior devuelve automáticamente los detalles del empleado asalariado máximo, sin realizar ningún cálculo por parte del desarrollador. Usando el marco de colecciones en Java, un desarrollador tiene que usar bucles y realizar comprobaciones repetidas. Otra preocupación es la eficiencia; como los procesadores multinúcleo están disponibles fácilmente, un desarrollador de Java tiene que escribir un procesamiento de código paralelo que puede ser bastante propenso a errores.
Para resolver estos problemas, Java 8 introdujo el concepto de flujo que permite al desarrollador procesar datos de forma declarativa y aprovechar la arquitectura multinúcleo sin necesidad de escribir ningún código específico para ello.
¿Qué es Corriente?
Stream representa una secuencia de objetos de una fuente, que admite operaciones agregadas. Las siguientes son las características de un Stream −
-
Secuencia de elementos − Un flujo proporciona un conjunto de elementos de tipo específico de manera secuencial. Una secuencia obtiene/calcula elementos a pedido. Nunca almacena los elementos.
-
Fuente − Stream toma colecciones, arreglos o recursos de E/S como fuente de entrada.
-
Operaciones agregadas − Stream admite operaciones agregadas como filtrar, mapear, limitar, reducir, buscar, unir, etc.
-
Canalización − La mayoría de las operaciones de flujo devuelven el flujo en sí mismo para que su resultado pueda canalizarse. Estas operaciones se denominan operaciones intermedias y su función es tomar entradas, procesarlas y devolver la salida al destino. El método collect() es una operación de terminal que normalmente está presente al final de la operación de canalización para marcar el final de la transmisión.
-
Iteraciones automáticas − Las operaciones de transmisión realizan las iteraciones internamente sobre los elementos de origen proporcionados, en contraste con las colecciones, donde se requiere una iteración explícita.
Generando flujos
Con Java 8, la interfaz de colección tiene dos métodos para generar un Stream.
-
flujo() − Devuelve un flujo secuencial considerando la colección como su fuente.
-
flujo paralelo() − Devuelve un Stream paralelo considerando la colección como su fuente.
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
paraCada
Stream ha proporcionado un nuevo método 'forEach' para iterar cada elemento de la secuencia. El siguiente segmento de código muestra cómo imprimir 10 números aleatorios usando forEach.
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
mapa
El método 'map' se usa para mapear cada elemento a su resultado correspondiente. El siguiente segmento de código imprime cuadrados únicos de números usando el mapa.
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());
filtro
El método de 'filtro' se utiliza para eliminar elementos en función de un criterio. El siguiente segmento de código imprime un recuento de cadenas vacías mediante filtro.
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.stream().filter(string -> string.isEmpty()).count();
límite
El método de "límite" se utiliza para reducir el tamaño de la corriente. El siguiente segmento de código muestra cómo imprimir 10 números aleatorios usando el límite.
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
ordenado
El método 'ordenado' se utiliza para ordenar el flujo. El siguiente segmento de código muestra cómo imprimir 10 números aleatorios en un orden ordenado.
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
Procesamiento en paralelo
ParallelStream es la alternativa de flujo para el procesamiento paralelo. Eche un vistazo al siguiente segmento de código que imprime un recuento de cadenas vacías utilizando ParalelStream.
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
Es muy fácil cambiar entre flujos secuenciales y paralelos.
Coleccionistas
Los recopiladores se utilizan para combinar el resultado del procesamiento de los elementos de un flujo. Los recopiladores se pueden usar para devolver una lista o una cadena.
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);
Estadísticas
Con Java 8, se introducen recopiladores de estadísticas para calcular todas las estadísticas cuando se realiza el procesamiento de secuencias.
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());
Ejemplo de transmisión
Cree el siguiente programa Java utilizando cualquier editor de su elección en, por ejemplo, C:\> JAVA.
Java8Tester.java
Demostración en vivoimport 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(); } }
Verificar el resultado
Compile la clase usando javac compilador de la siguiente manera −
C:\JAVA>javac Java8Tester.java
Ahora ejecute Java8Tester de la siguiente manera −
C:\JAVA>java Java8Tester
Debería producir el siguiente resultado −
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