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

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Streams de tipo específico y Paralelismo

26/39
Recursos

Aportes 20

Preguntas 5

Ordenar por:

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

Amo la API Stream y todas estas funcionalidades. Es una pena que a pesar de que Java 8 tiene como 9 años, muchos developers aún no utilizan todo esto.

De esta manera pude observar que se puede aprovechar la función .parallel( ):

IntStream infiniteStream = IntStream.iterate(0, x -> x + 1);
        infiniteStream.limit(1000)
                .parallel()
                .filter(x -> x % 2 == 0)
                .forEachOrdered(System.out::println);

La función .forEach opera iterando cada uno de los elementos contenidos en el Stream, sin embargo al hacerlo con la función .parallel( ) los toma a medida que se vayan completando las lineas de ejecución en cada procesador como dice el profesor, pero pude notar que si usamos .forEachOrdered va a tomar cada valor y los va a ordenar conforme vayan iterándose, al final obtendremos el mismo resultado pero con todos los elementos ordenados y chequeando los tiempos de ejecución la diferencia es considerable, en mi caso para este código el tiempo fue aproximadamente un 20% menos que hacerlo sin el .parallel( )

When to use Parallel Streams?

  1. They should be used when the output of the operation is not needed to be dependent on the order of elements present in source collection (i.e. on which the stream is created)

  2. Parallel Streams can be used in case of aggregate functions

  3. Parallel Streams quickly iterate over the large-sized collections

  4. Parallel Streams can be used if developers have performance implications with the Sequential Streams

  5. If the environment is not multi-threaded, then Parallel Stream creates thread and can affect the new requests coming in

Streams de tipo específico


Existen casos donde se quiere operar con Streams sobre tipos de datos incorporados en Java (como Integer o Double), es por eso que Java incorpora los Streams de tipo específico, los cuales permiten asegurar que las operaciones que se realicen sobre ellos trabajarán con el tipo de dato correspondiente.

List<String> numeros = Arrays.asList("0,37", "4,87", "1,23", "2,34", "3,45", "4,56");

DoubleStream doubleStream = numeros.stream()
        .map(numero -> numero.replace(",", ".")) // Reedecion las comas por puntos para que el Parse sea correcto
        .mapToDouble(Double::parseDouble) // Convierte los numeros de String a Double. A partir de acá se trabaja con DoubleStream en lugar de Stream
        .filter(numero -> numero < 1.5) // Filtra los numeros menores a 1.5
        .map(numero -> numero / 2) // Divide entre 2
        .sorted(); // Ordena los Doubles

Los Streams de tipo específico también permiten generar los datos en lugar de construirse a partir de una lista.

Por ejemplo, con IntStream.iterate se puede definir un número inicial y la Lambda que se usará para generar nuevos elementos.

// IntStream que contiene los primeros 100 años biciestos a partir del 1900
IntStream leapYears = IntStream.iterate(1900, x -> x + 1) // Genera numeros partiendo de 100 y aumentando 1 cada vez
        .filter(x -> x % 4 == 0) // los años bisiestos son divisibles entre 4
        .filter(x -> (x % 100 != 0) || (x % 100 == 0 && x % 400 == 0)) // pero si son divisibles entre 100 tambien deben serlo entre 400
        .limit(100); // limita a los 100 primeros años bisiestos

Es importante tener en cuenta que al generar Streams infinitos, se debe detener su generación en algún punto, de lo contrario se comportará como un bucle infinito (while (true)).


Streams con paralelismo


Existen casos donde se quiere operar los elementos de un Stream de forma paralela, es decir, que existan varios procesos tomando elementos distintos y procesarlos a la misma vez. Para crearlos a partir de una lista se puede utilizar la función parallelStream() en lugar de stream(), o si se tiene un Stream secuencial se puede convertir con parallel().

List<String> lenguajes = Arrays.asList("C#", "C++", "Go", "Java", "JavaScript", "PHP", "Python", "Ruby", "Swift", "TypeScript");

// Secuencial (ordenado)
lenguajes.stream()
        .forEach(System.out::println);

// Paralelo (desordenado)
lenguajes.parallelStream()
        .forEach(System.out::println);

Es importante tener en cuenta que al generar Streams paralelos no se mantiene el orden al iterar sobre él, ni tampoco existe un orden predecible en el Stream resultante.

Here, you can find a interesting example.

Hice la prueba con 1000000 y 10000000 con un millon el rendimiento en paralelo es un poco peor, pero con 10 millones el rendimiento mejora con paralel

datos:1000000
total milisegundosl:51611
Paralel
total milisegundos:52980
datos:10000000
total milisegundos:46821
Paralel
total milisegundos:46230

Parallelism: Parallel computing involves dividing a problem into subproblems, solving those problems simultaneously (in parallel, with each subproblem running in a separate thread), and then combining the results of the solutions to the subproblems.

Si tengo una lista de algún tipo dato:
List<Integer> integerList = Arrays.asList(1, 2, 3, … etc)

Y quiero utilizar un stream con paralelismo, entonces tengo que hacer lo siguiente??
integerList.stream().parallel()

O puedo utilizar:
integerList.parallelStream()

Ambas opciones son buenas prácticas?? y el resultado en ambas es el mismo??

Solo si te importa el orden de los datos es cuando NO deberías utilizar parallel()

Hasta el momento he aprendido muchas cosas nuevas

Stream por si misma es una clase y ay clases como "abstracStream" o "abstracImplemeitationStream", cosas por el estilo que java genera internamente para poder proveernos de estos Stream, pero aveces necesitamos un Stream de un tipo especifico, es posible que nosotros extendamos o implementemos de la clase Stream, pero tambien es posible que implementemos algunos elementos que esten ya predefinidos; por ejemplo algo muy comun es trabajar con primitivos, con numeros primitivos o con datos primitivos: Bits, Chard, Integer, Long, etc...

Una de las mejores clases del curso!

Si no entiendes de donde toma el parámetro de la x en el intUnaryOperator , entra a la definición del método iterate, hay se puede observar que el parámetro seed 0, es el que se envía como parámetro

Class stream recolacta los datos en un solo elemento con parallel

El orden de los valores no son seguidos sino conforme el procesador para terminado en paralelo lo van soltando

Stream con parallel funciona bien cuando son millones de datos, pero cuando son poco no debes de usar parallel

A través del método .parallel() podremos poner a trabajar los demás procesadores de nuestro equipo para que compilen más rápido el Stream y esto va ser ideal cuanto se manejen grandes cantidades de datos. Muchas gracias por la explicación instructor Sinuhé.

En caso tal necesito que se procesen rapido, pero despues necesito ordenarlos seria preferible mejor no utilizarlo entonces? De igual forma me parece genial Parallel(), diria que en termino de imprimir listas no se de personas sin importar el orden seria firme.

entendido 😃