Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Industrial programming >> Java

Java 8 Streams: Enfoque Declarativo para Procesamiento de Datos

Stream es una nueva capa abstracta introducida en Java 8. Usando stream, puedes procesar datos de forma declarativa similar a sentencias SQL. Por ejemplo, considera la siguiente sentencia SQL.

SELECT max(salary), employee_id, employee_name FROM Employee

La expresión SQL anterior devuelve automáticamente los detalles del empleado con mayor salario, sin hacer ningún cómputo por parte del desarrollador. Usando el framework de colecciones en Java, un desarrollador tiene que usar bucles y hacer comprobaciones repetidas. Otra preocupación es la eficiencia; como los procesadores multi-núcleo están disponibles fácilmente, un desarrollador de Java tiene que escribir código de procesamiento paralelo que puede ser bastante propenso a errores.

Para resolver tales problemas, Java 8 introdujo el concepto de stream que permite al desarrollador procesar datos declarativamente y aprovechar la arquitectura multi-núcleo sin necesidad de escribir código específico para ello.

¿Qué es Stream?

Stream representa una secuencia de objetos desde una fuente, que soporta operaciones agregadas. A continuación se muestran las características de un Stream:

Generar Streams

Con Java 8, la interfaz Collection tiene dos métodos para generar un Stream.

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

forEach

Stream ha proporcionado un nuevo método forEach para iterar cada elemento del stream. 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);

map

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 map.

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// obtener lista de cuadrados únicos
List<Integer> squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());

filter

El método filter se usa para eliminar elementos basándose en un criterio. El siguiente segmento de código imprime un conteo de cadenas vacías usando filter.

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// obtener conteo de cadena vacía
int count = strings.stream().filter(string -> string.isEmpty()).count();

limit

El método limit se usa para reducir el tamaño del stream. El siguiente segmento de código muestra cómo imprimir 10 números aleatorios usando limit.

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted

El método sorted se usa para ordenar el stream. El siguiente segmento de código muestra cómo imprimir 10 números aleatorios en orden.

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

Procesamiento Paralelo

parallelStream es la alternativa de stream para procesamiento paralelo. Echa un vistazo al siguiente segmento de código que imprime un conteo de cadenas vacías usando parallelStream.

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// obtener conteo de cadena vacía
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();

Es muy fácil cambiar entre streams secuenciales y paralelos.

Collectors

Los Collectors se usan para combinar el resultado del procesamiento en los elementos de un stream. Los Collectors pueden usarse 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("Lista Filtrada: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Cadena Combinada: " + mergedString);

Estadísticas

Con Java 8, se introducen colectores de estadísticas para calcular todas las estadísticas cuando se está procesando el stream.

List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Número más alto en Lista: " + stats.getMax());
System.out.println("Número más bajo en Lista: " + stats.getMin());
System.out.println("Suma de todos los números: " + stats.getSum());
System.out.println("Promedio de todos los números: " + stats.getAverage());

Ejemplo de Stream

Crea el siguiente programa Java usando cualquier editor de tu 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("Usando Java 7: ");
        // Contar cadenas vacías
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        System.out.println("Lista: " + strings);
        long count = getCountEmptyStringUsingJava7(strings);
        System.out.println("Cadenas Vacías: " + count);
        count = getCountLength3UsingJava7(strings);
        System.out.println("Cadenas de longitud 3: " + count);
        // Eliminar cadena vacía
        List<String> filtered = deleteEmptyStringsUsingJava7(strings);
        System.out.println("Lista Filtrada: " + filtered);
        // Eliminar cadena vacía y unir usando coma.
        String mergedString = getMergedStringUsingJava7(strings,", ");
        System.out.println("Cadena Combinada: " + mergedString);
        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        // obtener lista de cuadrados de números distintos
        List<Integer> squaresList = getSquares(numbers);
        System.out.println("Lista Cuadrados: " + squaresList);
        List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
        System.out.println("Lista: " + integers);
        System.out.println("Número más alto en Lista: " + getMax(integers));
        System.out.println("Número más bajo en Lista: " + getMin(integers));
        System.out.println("Suma de todos los números: " + getSum(integers));
        System.out.println("Promedio de todos los números: " + getAverage(integers));
        System.out.println("Números Aleatorios: ");
        // imprimir diez números aleatorios
        Random random = new Random();
        for(int i = 0; i < 10; i++) {
            System.out.println(random.nextInt());
        }
        System.out.println("Usando Java 8: ");
        System.out.println("Lista: " + strings);
        count = strings.stream().filter(string -> string.isEmpty()).count();
        System.out.println("Cadenas Vacías: " + count);
        count = strings.stream().filter(string -> string.length() == 3).count();
        System.out.println("Cadenas de longitud 3: " + count);
        filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        System.out.println("Lista Filtrada: " + filtered);
        mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
        System.out.println("Cadena Combinada: " + mergedString);
        squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
        System.out.println("Lista Cuadrados: " + squaresList);
        System.out.println("Lista: " + integers);
        IntSummaryStatistics stats = integers.stream().mapToInt((x) -> x).summaryStatistics();
        System.out.println("Número más alto en Lista: " + stats.getMax());
        System.out.println("Número más bajo en Lista: " + stats.getMin());
        System.out.println("Suma de todos los números: " + stats.getSum());
        System.out.println("Promedio de todos los números: " + stats.getAverage());
        System.out.println("Números Aleatorios: ");
        random.ints().limit(10).sorted().forEach(System.out::println);
        // procesamiento paralelo
        count = strings.parallelStream().filter(string -> string.isEmpty()).count();
        System.out.println("Cadenas Vacías: " + 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 el compilador javac de la siguiente manera:

C:\JAVA>javac Java8Tester.java

Ahora ejecuta Java8Tester de la siguiente manera:

C:\JAVA>java Java8Tester

Debería producir el siguiente resultado:

Usando Java 7:
Lista: [abc, , bc, efg, abcd, , jkl]
Cadenas Vacías: 2
Cadenas de longitud 3: 3
Lista Filtrada: [abc, bc, efg, abcd, jkl]
Cadena Combinada: abc, bc, efg, abcd, jkl
Lista Cuadrados: [9, 4, 49, 25]
Lista: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Número más alto en Lista: 19
Número más bajo en Lista: 1
Suma de todos los números: 85
Promedio de todos los números: 9
Números Aleatorios:
-1279735475
903418352
-1133928044
-1571118911
628530462
18407523
-881538250
-718932165
270259229
421676854
Usando Java 8:
Lista: [abc, , bc, efg, abcd, , jkl]
Cadenas Vacías: 2
Cadenas de longitud 3: 3
Lista Filtrada: [abc, bc, efg, abcd, jkl]
Cadena Combinada: abc, bc, efg, abcd, jkl
Lista Cuadrados: [9, 4, 49, 25]
Lista: [1, 2, 13, 4, 15, 6, 17, 8, 19]
Número más alto en Lista: 19
Número más bajo en Lista: 1
Suma de todos los números: 85
Promedio de todos los números: 9.444444444444445
Números Aleatorios:
-1009474951
-551240647
-2484714
181614550
933444268
1227850416
1579250773
1627454872
1683033687
1798939493
Cadenas Vacías: 2

Java

  1. Dominar Operadores en Java: Tipos, Sintaxis y Ejemplos Prácticos
  2. Comentarios en Java: Tipos, Uso y Mejores Prácticas
  3. Dominar el Bucle for Mejorado en Java: Sintaxis, Ejemplos y Mejores Prácticas
  4. Dominar Strings en Java: Creación, Métodos y Mejores Prácticas
  5. Dominando interfaces en Java: Conceptos, implementación y mejores prácticas
  6. Dominando las clases internas anónimas en Java: Definición, sintaxis y ejemplos prácticos
  7. Dominando Try‑with‑Resources en Java: Gestión automática de recursos explicada
  8. Anotaciones en Java explicadas: Tipos, ubicación y ejemplos prácticos
  9. Aserciones en Java: Guía práctica para detectar bugs y asegurar fiabilidad del código
  10. Generar números aleatorios en Java: Guía práctica con Random y Math.random
  11. Mejoras en Java 9 Stream API: takeWhile, dropWhile, iterate y ofNullable