Java: Map, Filter, Reduce

Volvemos con un tutorial, esta vez para hablar de la programación funcional en uno de los lenguajes más conocidos a lo largo de la historia, ni más ni menos que Java.


Programación funcional


Para empezar, hablemos de ¿qué es la programación funcional?


La programación funcional se basa en las queridas matemáticas, en la premisa de para una entrada X, dame una salida Y. Se puede ver resumido en esta imagen:





Java 8


A partir de la llegada de Java 8, esto se convirtio en algo que podíamos usar en este lenguaje, con los llamados Streams.


Para cada clase que implementa la interfaz Collection, ya pueda ser una Lista, un ArrayList, un Set, etc. Existe un método llamado stream(), que nos permite convertir ese conjunto de datos en un Stream.


Si trabajas con arrays, también tienes un método llamado Arrays.strema(array);


¿Y qué es un Stream?


Un Stream, es un flujo de datos, que nos va a permitir, realizar lo mostrado en la imagen anterior, esto a modo de definición simple y sencilla.


Ahora vamos a ver cómo implementar varios métodos de transformación, o varias funciones, que dada una entrada nos devolverán una salida, y transformarán el stream, en otro stream.


Método map


El primero de ellos es el map, método que nos permite transformar todos nuestros objetos, por ejemplo:


Supongamos que tenemos este stream de enteros: [9, 3, 5, 7, 8].


Y nosotros queremos que para cada elemento nos devuelva el doble, es decir, lo multiplique por 2, sería tal que así: [9, 3, 5, 7, 8].map(number -> number * 2);


¿Qué ocurre en el código anterior?


Lo que ocurre es que va obteniendo cada elemento, asignándolo a la variable number, lo multiplica por 2, devuelve el resultado y lo almacena en la misma posición.


Ejemplo, para el primer elemento:


[9, 3, 5, 7, 8].map(9 será 9 * 2) --> Nuevo stream: [18, 3, 5, 7, 8] y así sucesivamente hasta llegar al final.


Ejemplo en código Java


List<Integer> numbers = new ArrayList<>();

numbers.add(9);
numbers.add(3);
numbers.add(5);
numbers.add(7);
numbers.add(8);

Stream<Integer> stream = numbers.stream().map(number -> number * 2);

// Si queremos convertirlo a una lista, tenemos el método collect

List<Integer> newNumbers = stream.collect(Collectors.toList());

Esto es válido para objetos, strings y cualquier tipo de dato, practica y aprenderás más :)


Método filter


Este método nos permite filtrar los datos, digamos que tenemos un conjunto de objetos de tipo Persona, y queremos almacenar solo aquellos que sean mayores de edad, es decir, que tenga más de 18 años, supongamos que el objeto tiene 2 atributos: nombre y edad.


Ejemplo en código Java:



List<Person> people = new ArrayList<>();

people.add(new Person("Juan", 23));
people.add(new Person("Pedro", 18));
people.add(new Person("María", 15));
people.add(new Person("Verónica", 57));

List<Person> adults = people.stream().filter(person -> person.getAge() >= 18).collect(Collectors.toList());

Lo que hace el filter es lo mismo que el map, va recorriendo cada elemento, y aquellos que cumplan la condicion los conserva y los que no, los desecha, con el método getAge(), devolvemos la edad de cada persona, de esta forma sólo se quedarán aquellos cuya edad sea mayor o igual a 18, y lo asignamos a una nueva lista con el collect().


Método reduce


Este es el último de los métodos, nos sirve de acumulador, supongamos que tenemos un array de varios y números y queremos obtener la suma total, pues este método sumaría todos los valores y los acumularía en un solo valor, también sirve para la resta u otras operaciones como concatenar Strings.


Ejemplo


[7, 2, 3].reduce((acumulator, number) -> return acumulator + number);


Este código lo que hace es inicializar un acumulador a 0, y el number obtendrá cada valor, y lo almacenará en el acumulador.


1ª iteración:


Acumulator = 0, number = 7 -> acumulator + number = 7


2ª iteración:


Acumulator = 7, number = 2 -> acumulator + number = 9


3ª iteración:


Acumulator = 9, number = 3 -> acumulator + number = 12


Y el resultado será 12.


Ejemplo en código Java:


List<Integer> numbers = new List.of(7, 2, 3);

Integer result = numbers.stream().reduce((acc, val) -> {
                                           return acc + val
                                        }).get();                                                                                                                                                                                                                                                                                                                                                                                              

Bueno este ha sido un breve repaso a los métodos de programación funcional más usados y conocidos en Java, espero que te haya gustado y te haya servido nos vemos en la próxima :)

20 vistas0 comentarios

Entradas Recientes

Ver todo

©2020 por Juanma Perez.