1. Innovaciones en Java 8: Programación funcional

Con el lanzamiento de Java 8, el lenguaje obtuvo un poderoso soporte para la programación funcional . Incluso se podría decir que ganó el tan esperado soporte para la programación funcional. La codificación se volvió más rápida, aunque el código era más difícil de leer 🙂

Antes de aprender programación funcional en Java, te recomendamos que entiendas bien tres cosas:

  1. OOP, herencia e interfaces ( Niveles 1-2 en la búsqueda de Java Core ).
  2. Implementaciones de métodos predeterminados en una interfaz .
  3. Clases internas y anónimas .

La buena noticia es que no tienes que saber todo esto para usar muchas de las características de la programación funcional en Java. La mala noticia es que será difícil entender exactamente cómo está todo organizado y cómo funciona todo sin conocer las clases internas anónimas.

En las próximas lecciones, nos centraremos en lo fácil y simple que es usar las funciones de programación funcional de Java, sin una comprensión profunda de cómo funciona.

Lleva meses comprender todos los matices de la programación funcional en Java. Puede aprender a leer dicho código en unas pocas horas. Así que sugerimos empezar poco a poco. Incluso si es con flujos de E/S.


2. Flujos de E/S: canalizaciones de flujo

¿Recuerdas que alguna vez aprendiste sobre flujos de E/S: InputStream, OutputStream, Reader, Writeretc.?

Había clases de flujo que leían datos de orígenes de datos , como FileInputSteam, y flujos de datos intermedios que leían datos de otros flujos, como InputStreamReadery BufferedReader.

Estos flujos podrían organizarse en canalizaciones de procesamiento de datos. Por ejemplo, así:

FileInputStream input = new FileInputStream("c:\\readme.txt");
InputStreamReader reader = new InputStreamReader(input);
BufferedReader buff = new BufferedReader(reader);

String text = buff.readLine();

Es importante tener en cuenta que en las primeras líneas de código, solo estamos construyendo una cadena de Streamobjetos. Los datos aún no han pasado por la canalización.

Pero tan pronto como llamemos al buff.readLine()método, sucederá lo siguiente:

  1. El BufferedReaderobjeto llama al read()método en el InputStreamReaderobjeto.
  2. El InputStreamReaderobjeto llama al read()método en el FileInputStreamobjeto.
  3. El FileInputStreamobjeto comienza a leer datos del archivo.

En otras palabras, no hay movimiento de datos a lo largo de la tubería de transmisión hasta que comenzamos a llamar a métodos como read()o readLine(). La mera construcción de la canalización de flujo no conduce los datos a través de ella. Los flujos en sí mismos no almacenan datos. Sólo leen de los demás.

Colecciones y flujos

A partir de Java 8, se hizo posible obtener un flujo para leer datos de colecciones (y no solo de ellas). Pero esto no es lo más interesante. De hecho, se hizo posible construir de forma fácil y sencilla cadenas complejas de flujos de datos. Y al hacerlo, el código que antes ocupaba entre 5 y 10 líneas ahora se puede escribir en 1 o 2 líneas.

Ejemplo de cómo encontrar la cadena más larga en una lista de cadenas:

Encontrar la cuerda más larga
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String max = list.stream().max((s1, s2)-> s1.length()-s2.length()).get();
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
Stream<String> stream = list.stream();
Optional<String> optional = stream.max((s1, s2)-> s1.length()-s2.length());
String max = optional.get();

3. Streaminterfaz

El soporte extendido de Java 8 para flujos se implementa mediante la Stream<T>interfaz, donde Thay un parámetro de tipo que indica el tipo de datos que se pasan en el flujo. En otras palabras, un flujo es completamente independiente del tipo de datos que pasa.

Para obtener un objeto de flujo de una colección , simplemente llame a su stream()método. El código se ve más o menos así:

Stream<Type> name = collection.stream();
Obtener una transmisión de una colección

En este caso, la colección se considerará la fuente de datos del flujo y el Stream<Type>objeto será una herramienta para obtener datos de la colección en forma de flujo de datos.

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
Stream<String> stream = list.stream();

Por cierto, puede obtener una transmisión no solo de las colecciones, sino también de las matrices . Para hacer esto, necesitas usar el método. Por ejemplo:Arrays.stream()

Stream<Type> name = Arrays.stream(array);
Obtener una transmisión de una matriz

En este caso, la matriz se considerará la fuente de datos para el flujo llamado name.

Integer[] array = {1, 2, 3};
Stream<Integer> stream = Arrays.stream(array);

No se mueven datos cuando Stream<Type>se crea el objeto. Simplemente obtuvimos un objeto de flujo para comenzar a construir una canalización de flujo.