Java 8 - Streams

Stream es una nueva capa abstracta introducida en Java 8. Con stream, puede procesar datos de forma declarativa similar a las sentencias SQL. Por ejemplo, considere la siguiente declaració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. Al usar 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 de múltiples núcleos están disponibles con facilidad, 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 la necesidad de escribir ningún código específico para ello.

¿Qué es Stream?

Stream representa una secuencia de objetos de una fuente, que admite operaciones agregadas. Las siguientes son las características de una corriente:

  • Sequence of elements- Una secuencia proporciona un conjunto de elementos de tipo específico de manera secuencial. Una secuencia obtiene / calcula elementos a pedido. Nunca almacena los elementos.

  • Source - Stream toma colecciones, matrices o recursos de E / S como fuente de entrada.

  • Aggregate operations - Stream admite operaciones agregadas como filtrar, mapear, limitar, reducir, buscar, emparejar, etc.

  • Pipelining- La mayoría de las operaciones de flujo devuelven el flujo en sí mismo para que su resultado se pueda canalizar. Estas operaciones se denominan operaciones intermedias y su función es tomar entradas, procesarlas y devolver la salida al objetivo. 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 secuencia.

  • Automatic iterations - Las operaciones de transmisión realizan las iteraciones internamente sobre los elementos fuente proporcionados, en contraste con las colecciones donde se requiere una iteración explícita.

Generando corrientes

Con Java 8, la interfaz de Colección tiene dos métodos para generar una secuencia.

  • stream() - Devuelve una secuencia secuencial considerando la colección como su fuente.

  • parallelStream() - Devuelve una secuencia paralela 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());

para cada

Stream ha proporcionado un nuevo método 'forEach' para iterar cada elemento del flujo. 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 'mapa' se utiliza para asignar cada elemento a su resultado correspondiente. El siguiente segmento de código imprime cuadrados únicos de números usando 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());

filtrar

El método de 'filtro' se utiliza para eliminar elementos según un criterio. El siguiente segmento de código imprime un recuento de cadenas vacías usando 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();

límite

El método 'límite' se utiliza para reducir el tamaño de la secuencia. 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 la secuencia. 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

paraleloStream es la alternativa de flujo para procesamiento paralelo. Eche un vistazo al siguiente segmento de código que imprime un recuento de cadenas vacías usando paraleloStream.

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 secuencias secuenciales y paralelas.

Coleccionistas

Los recopiladores se utilizan para combinar el resultado del procesamiento en los elementos de una secuencia. Los recopiladores se pueden utilizar 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 la transmisión.

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, digamos, 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();
   }
}

Verificar el resultado

Compila 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