Stream y Lambdas en Java 8 👨‍💻
Tags: eclipse, beginners, java, tutorial
Published: 2023-10-08 11:50:11

## ¿Programación funcional en Java 8? 🤔🤔
Es interesante ver como java evolucionó permitiendo integrar funciones que pueden suplir a las clases, es decir se puede escribir **código declarativo** diciendo que se va hacer y no código con clases que implica el como se va hacer, y lo mas importante permite que este se adapte a tiempo de ejecución gracias a los **Genericos**, que identifican el tipo de variable con que se esta trabajando, pero entonces que pasaría si al final no arroja el tipo de dato que estamos buscando sino un **null** 😫😫 aquí mágicamente aparece otra característica que son los **Optional** que identifica si existe o no un dato 🤯🤯, de esta manera puedes respaldar el código que escribes sin necesidad de que este contenga exceptions innecesarios.

La maravilla se encuentra en que esto se vuelve como un juego de legos en que tu vas acomodando las piezas que necesitas y como lo necesitas, acortando así el total de código que vas a escribir.

## ¿Qué son Lambdas? 🤨🤨

Estos nacen gracias a la nueva anotación de _@FunctionalInterface_ que permite a las interfaces tener un método abstracto diferente a los definidos por Object (equals, hashcode, clone, etc) de manera que se pueda trabajar con funciones más explícitas y anonimas (Lambdas). Entonces, los lambdas son la manera en que Java ha encontrado para que se puedan escribir funciones anónimas sin necesidad de clases o instancias, de rápida ejecucción siendo lo mas transparente para el programador.

Existen 4 grandes grupos de interfaces funcionales ✍:

1. Predicate: Devuelve a fuerzas un boolean y normalmente es usada para validación de criterios (filtrar).
2. Supplier: Este tipo genera objetos sin que tenga argumentos.
3. Consumer: Es usada para consumir métodos del parámetro T (argumento que se pasa) causando así posibles efectos secundarios.
4. Function: Es usada para convertir de un parámetro de tipo T a otro de tipo R.

> Este tipo de funciones tienen variantes y se explican a más detalle en java.util.function encontrarás el link de la documentación en la bibliografía.

La forma en que podemos escribir Lambdas son de esta manera:

```
(a,b) -> Integer.sum(a,b)
(a,b) -> { 
    System.out.println("Los número a sumar son: " + a + " " + b);
    return Integer.sum(a,b) 
}
```

Como se nota cuando hay más de una línea de código se utiliza corchetes, además que se debe retornar el tipo de dato que se necesite o espere según sea el caso.

## Métodos de referencia 😎😎
A menudo encontrarás forma de escribir funciones lambdas un tanto particular y es que existen 3 casuísticas y otra con constructores que permiten acortar aún más el código.

1.- Métodos estáticos
Los métodos estáticos son aquellos que puedes invocar sin necesidad de instanciar un objeto específico de la clase. Para utilizar su referencia sería de esta manera **NombreClase::métodoEstático**.

- Ejemplo sin referencia

```
BinaryOperator<Integer> sum = (a,b) -> Integer.sum(a,b);
```

- Ejemplo con referencia

```
BinaryOperator<Integer> sum = Integer::sum;
```


2.- Instancia de un objeto
Cuando se cuenta con una referencua a un objeto y se desea invocar alguno de sus métodos de instancia dentro de la expresión lambda, sería de esta manera **RefObjeto::métodoInstancia**. Por ejemplo, la clase java.lang.System tiene una referencia a un  objeto de tipo java.io.PrintStream denominada out, usaremos  esa referencia para el siguiente ejemplo.

- Ejemplo sin referencia

```
Consumer<Integer> print = (a) -> System.out.println(a);
```

- Ejemplo con referencia

```
Consumer<Integer> print = System.out::println;
```

> La referencia al objeto se tiene en System.out y se invoca su método de instancia println(int): void


3.- Instancia de algún tipo
Se parece al anterior, aunque se diferencia en que no hay una referencia a un objeto, solo se conoce su tipo y se podría escribir una expresión lambda así **Tipo::métodoInstancia**.

- Ejemplo sin referencia

```
Comparator<String> upper = (a, b) -­> a.compareToIgnoreCase(b);
```

- Ejemplo con referencia

```
Comparator<String> upper = String::compareToIgnoreCase;
```

4.- Constructores
Se puede abreviar para los constructores ser escritos de esta manera **Clase::new** 

- Ejemplo sin referencia

```
Function<Integer, List> listSupplier = (num) -­> new ArrayList();
```

- Ejemplo con referencia

```
Function<Integer, List> listSupplier = ArrayList::new;
```


También podrían usarse los métodos de una clase sin que sean estáticos **Clase::método** esto serviría para cuando se desea obtener un valor específico para elaborar un stream. Para ello se tiene una lista de personas.

- Ejemplo sin referencia

```
IntStream edades = personas.stream().mapToInt(p -> p.getEdad());
```

- Ejemplo con referencia

```
IntStream edades = personas.stream().mapToInt(Persona::getEdad);
```

## Conclusión
Se ha revisado temas como:
- De donde provienen los lambdas y que aportan al momento de escribir código.
- Los tipos de funciones que se puede escribir, además de otras variedades que nos ofrecen en la documentación.
- Se ha conocido los métodos de referencia que permiten acortar el código sin que llegue a ser tan verboso.

Tal como lo hemos visto aún quedaría la duda de donde usarlo o lo mejor de todo como usarlo, para ello existen los **Stream** que son su complemento perfecto, con calma lectores que esta sería la primera parte de 3 artículos que esta relacionados entre sí, esta primera parte consta de explicar los **Lambdas**, para luego explicar que son los **Stream** y concluir con **ejercicios o casuísticas** donde pueden ser aplicados estos conceptos.

## Bibliografía
- https://www.oracle.com/mx/technical-resources/articles/java/expresiones-lambda-api-stream-java.html
- https://www.oracle.com/mx/technical-resources/articles/java/expresiones-lambda-api-stream-java-part2.html
- https://www.oracle.com/lad/technical-resources/articles/java/processing-streams-java-se8.html
- https://www.arteco-consulting.com/post/introduccion-a-java-lambda
- https://github.com/acelopezco/lambdas-lab/blob/master/src/main/java/com/javanme/java8/Avanzado.java
- https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html