Introducción a la programación Funcional

1

¿Qué es la Programación Funcional?

Entendiendo las partes de la programación funcional

2

¿Qué es una función en Java?

3

Funciones como ciudadanos de primera clase

4

Funciones puras

5

Entendiendo los efectos secundarios

6

Funciones de orden mayor

7

Funciones lambda

8

Inmutabilidad

Functional Programming en Java

9

Repositorio del curso

10

Configuración del entorno de trabajo

11

Revisando el paquete java.util.function: Function

12

Revisando el paquete java.util.function: Predicate

13

Revisando el paquete java.util.function: Consumer y Supplier

14

Revisando el paquete java.util.function: Operators y BiFunction

15

Entendiendo dos jugadores clave: SAM y FunctionalInterface

16

Operador de Referencia

17

Analizando la inferencia de tipos

18

Comprendiendo la sintaxis de las funciones lambda

19

Usando metodos default en nuestras interfaces

20

Dándole nombre a un viejo amigo: Chaining

21

Entendiendo la composición de funciones

Optional y Streams: Datos mas interesantes

22

La clase Optional

23

Entendiendo los Streams

24

¿Qué son los Stream listeners?

25

Operaciones y Collectors

26

Streams de tipo específico y Paralelismo

27

Operaciones Terminales

28

Operaciones Intermedias

29

Collectors

Todo junto: Proyecto Job-search

30

job-search: Un proyecto para encontrar trabajo

31

Vista rápida a un proyecto de Gradle

32

Revisando las opciones para nuestro CLI

33

Librerías adicionales para nuestro proyecto

34

Entendiendo la API de jobs

35

Diseñando las Funciones Constructoras de nuestro Proyecto

36

Agregando validaciones de datos

37

Diseñando las funciones de transformacion de datos

38

Creando flujos extras de transformación de Datos

Conclusiones

39

Un repaso a lo aprendido

Operaciones Intermedias

28/39

Lectura

En clases anteriores hablamos de dos tipos de operaciones: intermedias y finales. No se explicaron a profundidad, pero en esta lectura iremos más a fondo en las operaciones intermedias y trataremos de entender qué sucede por dentro de cada una.

...

Regístrate o inicia sesión para leer el resto del contenido.

Aportes 18

Preguntas 3

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

En el caso de flatMap, yo lo veo un poco más claro de esta forma:

    List<Email> allEmailsToNotify = getPlatziUsers()
      .stream()
      .filter(PlatziStudent::isEmailSubscribed)
      .map(PlatziStudent::getEmails)
      .flatMap(Collection::stream)
      .collect(Collectors.toList());

Se nota un poco mejor que el Stream<Stream<Email>> se convierte en Stream<Email>, que finalmente se transforma en List<Email>.

Los que tienen dudas aún sobre el uso de flatMap con este articulo pueden aclarar las dudas.

Les dejo la documentación oficial de Stream por si están interesados. Documentacion

Con respecto al hacer _chaining _de operaciones filter, si bien facilita su legibilidad pero me parece que afecta el performance. Ya que, si tenemos un stream de 1000 cursos por ejemplo, al hacer:

courses.filter(course -> course.getName().contains("Java"))
    .filter(course -> course.getDuration() > 2.5)
    .filter(course -> course.getInstructor().getName() == Instructors.SINUHE_JAIME)

en el peor de los casos (cuando ninguna condición se cumpla) por cada .filter estaríamos haciendo 1000 iteraciones quedando en 3000 iteraciones en total. En cambio si hacemos algo como:

courses.filter(course -> course.getName().contains("Java") && course.getDuration() > 2.5 && course.getInstructor().getName() == Instructors.SINUHE_JAIME);

Solo serian 1000.

Por favor, corrijanme si me equivoco

No me quedo del todo claro el uso del flatMap, tal vez otro ejemplo me ayudaría.

Muchas gracias por la explicación de Operaciones Intermedias instructor Sinuhé. Por cierto, respecto al .limit tengo entendido que se usaría de esta manera para establecer el nuevo rango de los elementos en un stream:

Stream<String> firstGeneration = pokemonNamesStream.limit(151);

Wow! Con skip() y limit() puedo hacer lo mismo que hago con PostgreSQL: https://www.postgresql.org/docs/8.1/queries-limit.html

Esto me será muy útil para la paginación de mis APIs: https://www.baeldung.com/rest-api-pagination-in-spring

https://www.arquitecturajava.com/java-8-flatmap/

un ejemplo para entender mas facilmente el flatMap

Operación intermedia limit

public Stream limit(Long limit){
        List list = new LinkedList<>();
        for (int i = 0; i < limit; i++){
            list.add(this.data);
        }
        return list.stream();
    }

Se le dice operación intermedia a toda operación dentro de un Stream que como resultado devuelva un nuevo Stream.

Aporto el uso de Limit, con un List de Strings

   public static void main(String[] args) {
        List<String> stringNames = new ArrayList<>();
        stringNames.add("Juan Manuel");
        stringNames.add("Juan Pablo");
        stringNames.add("Juan Andres");
        stringNames.add("Juan Emanuel");

        Stream<String> listStream =stringNames.stream();

        Collection<String> namesLimited = listStream.limit(2).collect(Collectors.toList());

        System.out.println(namesLimited);
    }

Apuntes de operaciones skip ,limit , Sorted

  • con Sorted debemos implemantar la interfaz Comparable<T> para tener un parametro de comparacion
	List<String> emails = Arrays.asList("asdf@23","kjhgtre@hgfd","zadfsv@234");
	
	emails.forEach(System.out::println);

	}
	
	public class Entity implements Comparable<Entity>{
		
		String direccion;
		
		@Override
		public int compareTo(Entity o) {
			// TODO Auto-generated method stub
			return this.direccion.compareTo(o.direccion) ;
		}
  • Limit and Skip

	
	List<Integer> first3Numbers = Arrays.asList(0,1,2,3,4,5,6,7,8,9);
	Stream<Integer> last3Numbers = Stream.of(3,4,5,6,7,8,9);
	
	
	// limit trae los 3  primeros elementos de mi coleccion
	first3Numbers.stream().limit(3).forEach(x-> System.out.println(x));// 0,1,2
	
	// skip omite los primeros 4 elementos de mi coleccion
	last3Numbers.skip(4).forEach(x-> System.out.println(x));//7,8,9


	

	
}

el ejemplo de flatMap
esta incompleto

creo que era map

public  Stream filter(Function mapper) {
    List mappedData = new LinkedList<>();
    for(T t : this.data){
        R r = mapper.apply(t);
        mappedData.add(r);
    }

    return mappedData.stream();
} 

Implementación de limit:

class Nothing { 
      
     // Driver code 
     public static void main(String[] args){ 
           
         // list to save stream of strings 
         List<String> arr = new ArrayList<>(); 
           
         arr.add("geeks"); 
         arr.add("for"); 
         arr.add("geeks"); 
         arr.add("computer"); 
         arr.add("science"); 
          
         Stream<String> str = arr.stream(); 
           
         // calling function to limit the stream to range 3 
         Stream<String> lm = str.limit(3); 
         lm.forEach(System.out::println); 
     } 
 } 

Siempre buscar lo mas adecuado con estas nuevas herramientas que nos ofrece Java y utilizar e investigar antes de implementar las mismas formas de código de Java.

Genial

Algo que noté con Java 11 no sé si aplica en Java 8, es que el map, no se ejecuta hasta que el stream sea consumido por otra operación.