Cómo aprender la API de flujo de Java [+5 Resources]

Una secuencia en Java es una secuencia de elementos sobre los que se pueden realizar operaciones secuenciales o paralelas.

Puede haber un número “n” de operaciones intermedias y, por último, una operación terminal, tras la cual se devuelve el resultado.

¿Qué es una corriente?

Los flujos se pueden administrar mediante la API de flujo, que se introdujo en Java 8.

Imagine Stream como una canalización de fabricación en la que es necesario fabricar, clasificar y empaquetar algunos productos para su envío. En Java, esos bienes son objetos o colecciones de objetos, las operaciones son la fabricación, clasificación y empaque, y la canalización es el flujo.

Los componentes de una corriente son:

  • Una entrada inicial
  • Operaciones intermedias
  • Operación de terminales
  • Resultado final

Exploremos algunas características de una secuencia en Java:

  • Stream no es una estructura de datos en memoria; más bien, es una secuencia de arreglos, objetos o colecciones de objetos que son operados por ciertos métodos.
  • Los flujos son de naturaleza declarativa, es decir, se especifica qué hacer pero no cómo hacerlo.
  • Se pueden consumir una sola vez ya que no se almacenan en ningún lado.
  • Stream no modifica la estructura de datos original; sólo deriva una nueva estructura de ella.
  • Devuelve el resultado final derivado del método final en la canalización.

Stream API vs. Procesamiento de colecciones

Una colección es una estructura de datos en memoria que almacena y procesa datos. Las colecciones proporcionan estructuras de datos como Conjunto, Mapa, Lista, etc., para almacenar datos. Por otro lado, una transmisión es una forma de transferir datos de manera eficiente después de procesarlos a través de una canalización.

Aquí hay un ejemplo de una colección ArrayList: –

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(0, 3);
        System.out.println(list);
    }
}

Output: 
[3]

Como puede ver en el ejemplo anterior, puede crear una colección ArrayList, almacenar datos en ella y luego operar con esos datos usando diferentes métodos.

Usando una secuencia, puede operar en una estructura de datos existente y devolver un nuevo valor modificado. A continuación se muestra un ejemplo de cómo crear una colección ArrayList y filtrarla mediante una transmisión.

import java.util.ArrayList;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList();

        for (int i = 0; i < 20; i++) {
            list.add(i+1);
        }

        System.out.println(list);

        Stream<Integer> filtered = list.stream().filter(num -> num > 10);
        filtered.forEach(num -> System.out.println(num + " "));
    }
}

#Output

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 

En el ejemplo anterior, se crea una secuencia usando la lista existente, y la lista se itera para filtrar valores superiores a 10. Observe que la secuencia no almacena nada, solo se itera sobre la lista y se imprime el resultado. Si intenta imprimir la transmisión, obtendrá una referencia a la transmisión en lugar de valores.

Trabajando en la API de flujo de Java

La API de flujo de Java toma una colección fuente de elementos o una secuencia de elementos y luego realiza operaciones en ellos para obtener un resultado final. Una secuencia es solo una tubería a través de la cual pasa una secuencia de elementos y se transforma de alguna manera.

Se puede crear una transmisión a partir de varias fuentes, que incluyen:

  • Una colección como una lista o un conjunto.
  • Una matriz.
  • Desde archivos y sus rutas usando un búfer.

Hay dos tipos de operaciones realizadas en una secuencia: –

  • Operaciones Intermedias
  • operaciones de terminales

Operaciones intermedias vs. terminales

Cada operación intermedia devuelve una nueva secuencia internamente que transforma la entrada utilizando el método especificado. En realidad, nada se atraviesa; En su lugar, se pasa a la siguiente secuencia. Es solo en la operación terminal que se atraviesa la corriente para obtener el resultado deseado.

Por ejemplo, tiene una lista de 10 números que desea filtrar y luego asignar a algo. No todos los elementos de la lista se recorrerán inmediatamente para obtener el resultado filtrado y asignarlo a otra cosa. En su lugar, se comprobarán los elementos individuales y, si cumplen la condición, se asignarán. Nuevos flujos para todos y cada uno de los elementos.

La operación de mapa se realizará en elementos individuales que satisfagan el filtro y no en la lista completa. Y en el momento de la operación terminal, se recorren y se combinan en un solo resultado.

Después de realizar la operación de terminal, la transmisión se consume y ya no se puede usar más. Debe crear una nueva secuencia para volver a realizar las mismas operaciones.

Fuente: The Bored Dev

Con una comprensión superficial de cómo funcionan los flujos, pasemos a los detalles de implementación de los flujos en Java.

#1. Una corriente vacía

Cree una transmisión vacía utilizando el método vacío de la API de transmisión.

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream emptyStream = Stream.empty();
        System.out.println(emptyStream.count());
    }
}

Output:
0

Aquí, si imprime la cantidad de elementos en esta secuencia, obtiene 0 como salida porque es una secuencia vacía sin elementos. Los flujos vacíos son bastante útiles para evitar excepciones de puntero nulo.

#2. Transmitir desde colecciones

Las colecciones como Lists y Set exponen un método stream() que le permite crear una secuencia a partir de una colección. La secuencia creada se puede recorrer para obtener el resultado final.

ArrayList<Integer> list = new ArrayList();

for (int i = 0; i < 20; i++) {
    list.add(i+1);
}

System.out.println(list);

Stream<Integer> filtered = list.stream().filter(num -> num > 10);
filtered.forEach(num -> System.out.println(num + " "));

#Output

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 

#3. Transmitir desde arreglos

El método Arrays.stream() se usa para crear una secuencia a partir de una matriz.

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] stringArray = new String[]{"this", "is", "kirukiru.es"};
        Arrays.stream(stringArray).forEach(item -> System.out.print(item + " "));
    }
}

#Output

this is kirukiru.es 

También puede especificar el índice inicial y final de los elementos para crear una secuencia. El índice inicial es inclusivo, mientras que el índice final es exclusivo.

String[] stringArray = new String[]{"this", "is", "kirukiru.es"};
Arrays.stream(stringArray, 1, 3).forEach(item -> System.out.print(item + " "));

Output:
is kirukiru.es

#4. Encontrar números mínimos y máximos usando Streams

Se puede acceder al número máximo y mínimo de una colección o una matriz utilizando Comparators en Java. Los métodos min() y max() aceptan un comparador y devuelven un objeto Opcional.

Un objeto opcional es un objeto contenedor que puede o no contener un valor no nulo. Si contiene un valor no nulo, llamar al método get() devolverá el valor.

import java.util.Arrays;
import java.util.Optional;

public class MinMax {
    public static void main(String[] args) {
        Integer[] numbers = new Integer[]{21, 82, 41, 9, 62, 3, 11};

        Optional<Integer> maxValue = Arrays.stream(numbers).max(Integer::compare);
        System.out.println(maxValue.get());

        Optional<Integer> minValue = Arrays.stream(numbers).min(Integer::compare);
        System.out.println(minValue.get());
    }
}

#Output
82
3

Recursos de aprendizaje

Ahora que tiene una comprensión básica de Streams en Java, aquí hay 5 recursos para que se familiarice bien con Java 8:

#1. Java 8 en acción

Este libro es una guía que muestra las nuevas características de Java 8, incluidas secuencias, lambdas y programación de estilo funcional. Los cuestionarios y las preguntas de verificación de conocimientos también forman parte del libro, que lo ayudarán a recuperar lo aprendido.

Puede obtener este libro en formato de bolsillo, así como en formato de audiolibro en Amazon.

#2. Java 8 Lambdas: programación funcional para las masas

Este libro está diseñado específicamente para enseñar a los principales desarrolladores de Java SE cómo la adición de expresiones Lambda afecta al lenguaje Java. Incluye explicaciones fluidas, ejercicios de código y ejemplos para que domine las expresiones lambda de Java 8.

Está disponible en formato de bolsillo y edición Kindle en Amazon.

#3. Java SE 8 para los realmente impacientes

Si es un desarrollador experimentado de Java SE, este libro lo guiará a través de las mejoras realizadas en Java SE 8, la API de transmisión, la adición de expresiones lambda, mejoras en la programación concurrente en Java y algunas características de Java 7 que la mayoría de la gente no conoce. no sé sobre

Solo está disponible en formato de bolsillo en Amazon.

#4. Aprenda programación funcional Java con Lambdas y Streams

Este curso de Udemy explora los fundamentos de la programación funcional en Java 8 y 9. Las expresiones lambda, las referencias a métodos, los flujos y las interfaces funcionales son los conceptos en los que se centra este curso.

También incluye un montón de rompecabezas y ejercicios de Java relacionados con la programación funcional.

#5. Biblioteca de clases de Java

La biblioteca de clases de Java es parte de la especialización básica de Java que ofrece Coursera. Le enseñará cómo escribir código con seguridad de tipo utilizando Java Generics, comprender la biblioteca de clases que consta de más de 4000 clases, cómo trabajar con archivos y manejar errores de tiempo de ejecución. Sin embargo, hay algunos requisitos previos para tomar este curso:

  • Introducción a Java
  • Introducción a la Programación Orientada a Objetos con Java
  • Jerarquías orientadas a objetos en Java

Ultimas palabras

La API Java Stream y la introducción de funciones Lambda en Java 8 simplificaron y mejoraron muchas cosas en Java, como iteración paralela, interfaces funcionales, menos código, etc.

Sin embargo, las transmisiones tienen algunas limitaciones; su mayor limitación es que solo se pueden consumir una vez. Si es un desarrollador de Java, los recursos mencionados anteriormente pueden ayudarlo a comprender estos temas con mucho más detalle, así que asegúrese de consultarlos.

Es posible que también desee saber sobre el manejo de excepciones en Java.