SlideShare una empresa de Scribd logo
1 de 215
Descargar para leer sin conexión
LAMBDAS & STREAM API
JAVA 8
@SuperSerch
INTRODUCCIÓN
¿POR QUÉ TENER LAMBDAS Y STREAMS?
▸ Facilitar la programación concurrente
▸ Reducir los errores al programar iteraciones de
colecciones
CASO DE EJEMPLO
PERSON
class Person {
int getAge();
Sex getSex();
PhoneNumber getPhoneNumber();
EmailAddr getEmailAddr();
PostalAddr getPostalAddr();
...
}
enum Sex { FEMALE, MALE }
CASO DE EJEMPLO
ROBOCALL - PERSONAS EN EDAD DE CONDUCIR
class MyApplication {
List<Person> list = ...
void robocallEligibleDrivers() {
...
}
...
}
CASO DE EJEMPLO
ROBOCALL - PERSONAS EN EDAD DE CONDUCIR
void robocallEligibleDrivers() {
for (Person p : list) {
if (p.getAge()>=16){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
ROBOCALL - PERSONAS EN EDAD DE VOTAR
CASO DE EJEMPLO
ROBOCALL - PERSONAS EN EDAD DE VOTAR
void robocallEligibleVoters() {
for (Person p : list) {
if (p.getAge()>=18){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
ROBOCALL - PERSONAS EN EDAD DE BEBER
CASO DE EJEMPLO
ROBOCALL - PERSONAS EN EDAD DE BEBER
void robocallEligibleDrinkers() {
for (Person p : list) {
if (p.getAge()>=21){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
ROBOCALL - PERSONAS EN EDAD DE BEBER
void robocallEligibleDrinkers() {
for (Person p : list) {
if (p.getAge()>=21){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CÓDIGO REPETIDO
CASO DE EJEMPLO
SOLUCIÓN PARAMETRIZAR!
CASO DE EJEMPLO
SOLUCIÓN PARAMETRIZAR!
void robocallOlderThan(int age) {
for (Person p : list) {
if (p.getAge()>=age){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
USANDO PARÁMETROS
void robocallEligibleDrivers() {
robocallOlderThan(16);
}
void robocallEligibleVoters() {
robocallOlderThan(18);
}
void robocallEligibleDrinkers() {
robocallOlderThan(21);
}
CASO DE EJEMPLO
CAMBIAN LOS REQUERIMIENTOS
▸ Enviar publicidad a potenciales pilotos comerciales
▸ edad mínima de 23
▸ pero retiro mandatorio a los 65
▸ Agregamos otro parámetro y ahora buscamos rangos
▸ usamos Integer.MAX_VALUE para el tope superior si sólo
tenemos el límite inferior
▸ usamos 0 para el tope inferior si sólo tenemos el límite
superior
CASO DE EJEMPLO
CON RANGO DE EDAD
void robocallAgeRange(int low, int high) {
for (Person p : list) {
if (low <= p.getAge() && p.getAge() < high){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
USANDO RANGO DE EDAD
void robocallEligiblePilots() {
robocallAgeRange(23, 65);
}
void robocallEligibleDrivers() {
robocallAgeRange(16, Integer.MAX_VALUE);
}
void robocallEligibleVoters() {
robocallAgeRange(18, Integer.MAX_VALUE);
}
void robocallEligibleDrinkers() {
robocallAgeRange(21, Integer.MAX_VALUE);
}
CASO DE EJEMPLO
UN REQUERIMIENTO MÁS
▸ Enviar publicidad a obligados a cumplir servicio militar
▸ con edades entre 18 y 26
▸ sólo hombres
CASO DE EJEMPLO
UN REQUERIMIENTO MÁS
▸ Enviar publicidad a obligados a cumplir servicio militar
▸ con edades entre 18 y 26
▸ sólo hombres
void robocallSelectiveService() {
robocallSexAgeRange(Sex.MALE, 18, 26);
}
CASO DE EJEMPLO
CON SEXO Y RANGO DE EDAD
void robocallSexAgeRange(Sex sex, int low, int high) {
for (Person p : list) {
if (p.getSex() == sex &&
low <= p.getAge() && p.getAge() < high){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
PERO AL COLOCARLO EN LOS CASOS PREVIOS
void robocallEligiblePilots() {
robocallSexAgeRange(???, 23, 65);
}
void robocallEligibleDrivers() {
robocallSexAgeRange(???, 16, Integer.MAX_VALUE);
}
void robocallEligibleVoters() {
robocallSexAgeRange(???, 18, Integer.MAX_VALUE);
}
void robocallEligibleDrinkers() {
robocallSexAgeRange(???, 21, Integer.MAX_VALUE);
}
CASO DE EJEMPLO
PERO AL COLOCARLO EN LOS CASOS PREVIOS
void robocallEligiblePilots() {
robocallSexAgeRange(???, 23, 65);
}
void robocallEligibleDrivers() {
robocallSexAgeRange(???, 16, Integer.MAX_VALUE);
}
void robocallEligibleVoters() {
robocallSexAgeRange(???, 18, Integer.MAX_VALUE);
}
void robocallEligibleDrinkers() {
robocallSexAgeRange(???, 21, Integer.MAX_VALUE);
}
CASO DE EJEMPLO
INTENTO #1 DE ARREGLARLO
enum Sex { FEMALE, MALE, DONT_CARE }
void robocallSexAgeRange(Sex sex, int low, int high)
{
for (Person p : list) {
if ((sex == DONT_CARE || p.getSex() == sex) &&
low <= p.getAge() && p.getAge() < high){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
INTENTO #1 DE ARREGLARLO
enum Sex { FEMALE, MALE, DONT_CARE }
void robocallSexAgeRange(Sex sex, int low, int high)
{
for (Person p : list) {
if ((sex == DONT_CARE || p.getSex() == sex) &&
low <= p.getAge() && p.getAge() < high){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
INTENTO #1 DE ARREGLARLO
enum Sex { FEMALE, MALE, DONT_CARE }
void robocallSexAgeRange(Sex sex, int low, int high)
{
for (Person p : list) {
if ((sex == DONT_CARE || p.getSex() == sex) &&
low <= p.getAge() && p.getAge() < high){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
IMPLEMENTACIÓN
CONTAMINA EL
MODELO
CASO DE EJEMPLO
INTENTO #2 DE ARREGLARLO - USAR NULL
void robocallSexAgeRange(Sex sex, int low, int high) {
for (Person p : list) {
if ((sex == null || p.getSex() == sex) &&
low <= p.getAge() && p.getAge() < high){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
AL COLOCARLO EN LOS CASOS PREVIOS
void robocallSelectiveService() {
robocallSexAgeRange(Sex.MALE, 18, 26);
}
void robocallEligiblePilots() {
robocallSexAgeRange(null, 23, 65);
}
void robocallEligibleDrivers() {
robocallSexAgeRange(null, 16, Integer.MAX_VALUE);
}
CASO DE EJEMPLO
AL COLOCARLO EN LOS CASOS PREVIOS
void robocallSelectiveService() {
robocallSexAgeRange(Sex.MALE, 18, 26);
}
void robocallEligiblePilots() {
robocallSexAgeRange(null, 23, 65);
}
void robocallEligibleDrivers() {
robocallSexAgeRange(null, 16, Integer.MAX_VALUE);
}
▸ Pero, ¿y si sex==null significa que no se capturó el sexo?
CASO DE EJEMPLO
INTENTO #3 AGREGAR UN BOOLEAN
void robocallSexAgeRange(Sex sex, boolean checkSex,
int low, int high) {
for (Person p : list) {
if ((!checkSex || p.getSex() == sex) &&
low <= p.getAge() && p.getAge() < high){
Phonenumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
AL COLOCARLO EN LOS CASOS PREVIOS
void robocallSelectiveService() {
robocallSexAgeRange(Sex.MALE, true, 18, 26);
}
void robocallEligiblePilots() {
robocallSexAgeRange(null, false, 23, 65);
}
void robocallEligibleDrivers() {
robocallSexAgeRange(Sex.MALE, false, 16,
Integer.MAX_VALUE);
}
CASO DE EJEMPLO
AL COLOCARLO EN LOS CASOS PREVIOS
void robocallSelectiveService() {
robocallSexAgeRange(Sex.MALE, true, 18, 26);
}
void robocallEligiblePilots() {
robocallSexAgeRange(null, false, 23, 65);
}
void robocallEligibleDrivers() {
robocallSexAgeRange(Sex.MALE, false, 16,
Integer.MAX_VALUE);
}
▸ aún hay que poner algo en el campo de sex, incluso si es ignorado
CASO DE EJEMPLO
AL COLOCARLO EN LOS CASOS PREVIOS
void robocallSelectiveService() {
robocallSexAgeRange(Sex.MALE, true, 18, 26);
}
void robocallEligiblePilots() {
robocallSexAgeRange(null, false, 23, 65);
}
void robocallEligibleDrivers() {
robocallSexAgeRange(Sex.MALE, false, 16,
Integer.MAX_VALUE);
}
▸ aún hay que poner algo en el campo de sex, incluso si es ignorado
▸ ¿Y si olvidamos cambiar el boolean al cambiar la llamada?
CASO DE EJEMPLO
LO QUE EL CALLER QUIERE
void robocallSelectiveService() {
robocallMatchingPersons(*******)
}
CASO DE EJEMPLO
LO QUE EL CALLER QUIERE
void robocallSelectiveService() {
robocallMatchingPersons(*******)
}
▸ *** dada una persona, usando características de la persona,
decidir cuando esa persona deberá ser robo-llamada
CASO DE EJEMPLO
LO QUE LA BIBLIOTECA QUIERE
void robocallMatchingPersons(********) {
for (Person p : list) {
if (***) {
PhoneNumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
LO QUE LA BIBLIOTECA QUIERE
void robocallMatchingPersons(********) {
for (Person p : list) {
if (***) {
PhoneNumber num = p.getPhoneNumber();
robocall(num);
}
}
}
CASO DE EJEMPLO
LO QUE LA BIBLIOTECA QUIERE
void robocallMatchingPersons(********) {
for (Person p : list) {
if (***) {
PhoneNumber num = p.getPhoneNumber();
robocall(num);
}
}
}
ES UNA FUNCIÓN!
CASO DE EJEMPLO
LO QUE LA BIBLIOTECA QUIERE
void robocallMatchingPersons(********) {
for (Person p : list) {
if (***) {
PhoneNumber num = p.getPhoneNumber();
robocall(num);
}
}
}
ES UNA FUNCIÓN!
▸ Función dada una persona, usando características de la
persona, decidir cuando esa persona deberá ser robo-llamada
▸ El parámetro de esa función es una Persona
▸ El resultado de esa función es un boolean
LAMBDAS
¿QUÉ ES UNA EXPRESIÓN LAMBDA? λ
LAMBDAS
¿QUÉ ES UNA EXPRESIÓN LAMBDA?
▸ Forma matemática que define la transformación de un
valor
λ
LAMBDAS
¿QUÉ ES UNA EXPRESIÓN LAMBDA?
▸ Forma matemática que define la transformación de un
valor
▸ A las cosas que realizan transformaciones las
denominamos Funciones
λ
LAMBDAS
¿QUÉ ES UNA EXPRESIÓN LAMBDA?
▸ Forma matemática que define la transformación de un
valor
▸ A las cosas que realizan transformaciones las
denominamos Funciones
▸ int -> int 

Función que transforma de entero a entero
λ
LAMBDAS
¿QUÉ ES UNA EXPRESIÓN LAMBDA?
▸ Forma matemática que define la transformación de un
valor
▸ A las cosas que realizan transformaciones las
denominamos Funciones
▸ int -> int 

Función que transforma de entero a entero
▸ Las expresiones Lambda son la manera de agregar
funciones a Java
λ
LAMBDAS
PROPÓSITO DE LAS EXPRESIONES LAMBDA
LAMBDAS
PROPÓSITO DE LAS EXPRESIONES LAMBDA
▸ Proveen una manera sencilla para distribuir procesamiento
específico
LAMBDAS
PROPÓSITO DE LAS EXPRESIONES LAMBDA
▸ Proveen una manera sencilla para distribuir procesamiento
específico
▸ Útiles para procesar colecciones
LAMBDAS
PROPÓSITO DE LAS EXPRESIONES LAMBDA
▸ Proveen una manera sencilla para distribuir procesamiento
específico
▸ Útiles para procesar colecciones
▸ Facilitar la cooperación entre desarrolladores y usuarios
de bibliotecas
LAMBDAS
PROPÓSITO DE LAS EXPRESIONES LAMBDA
▸ Proveen una manera sencilla para distribuir procesamiento
específico
▸ Útiles para procesar colecciones
▸ Facilitar la cooperación entre desarrolladores y usuarios
de bibliotecas
▸ (T p, T2 q, …) -> {bloque de código}
LAMBDAS
¿CÓMO REPRESENTAMOS FUNCIONES EN JAVA?
new Thread(new Runnable() {
public void run() {
System.out.println("Estoy en otro hilo.");
}
}).start();
Collections.sort(people, new Comparator<Person>() {
public int compare(Person x, Person y) {
return
x.getLastName().compareTo(y.getLastName());
}
});
LAMBDAS
LAMBDAS
LAMBDAS
LAMBDAS
▸ Bloque de código
LAMBDAS
LAMBDAS
▸ Bloque de código
▸ Se basan en Target Typing (Según el contexto se
determina el tipo de la Lambda)
LAMBDAS
LAMBDAS
▸ Bloque de código
▸ Se basan en Target Typing (Según el contexto se
determina el tipo de la Lambda)
▸ existen en dos categorías:
LAMBDAS
LAMBDAS
▸ Bloque de código
▸ Se basan en Target Typing (Según el contexto se
determina el tipo de la Lambda)
▸ existen en dos categorías:
▸ Sin efectos colaterales
LAMBDAS
LAMBDAS
▸ Bloque de código
▸ Se basan en Target Typing (Según el contexto se
determina el tipo de la Lambda)
▸ existen en dos categorías:
▸ Sin efectos colaterales
▸ Con efectos colaterales
LAMBDAS
LAMBDAS
▸ Bloque de código
▸ Se basan en Target Typing (Según el contexto se
determina el tipo de la Lambda)
▸ existen en dos categorías:
▸ Sin efectos colaterales
▸ Con efectos colaterales
▸ Siempre asignadas a una Functional Interface
FUNCTIONAL INTERFACE
FUNCTIONAL INTERFACE @FunctionalInterface
FUNCTIONAL INTERFACE
FUNCTIONAL INTERFACE
▸ Interfaces que tienen sólo un método abstracto.
@FunctionalInterface
FUNCTIONAL INTERFACE
FUNCTIONAL INTERFACE
▸ Interfaces que tienen sólo un método abstracto.
▸ Los métodos por defecto, dado que ya están implementados,
no cuentan para definir si una Interface es funcional o no
@FunctionalInterface
FUNCTIONAL INTERFACE
FUNCTIONAL INTERFACE
▸ Interfaces que tienen sólo un método abstracto.
▸ Los métodos por defecto, dado que ya están implementados,
no cuentan para definir si una Interface es funcional o no
▸ Si la interface declara un método abstracto, pero que
sobreescribe un método de java.lang.Object, este tampoco
cuenta para definir si es funcional o no
@FunctionalInterface
FUNCTIONAL INTERFACE
FUNCTIONAL INTERFACE
▸ Interfaces que tienen sólo un método abstracto.
▸ Los métodos por defecto, dado que ya están implementados,
no cuentan para definir si una Interface es funcional o no
▸ Si la interface declara un método abstracto, pero que
sobreescribe un método de java.lang.Object, este tampoco
cuenta para definir si es funcional o no
▸ Multiples Interfaces se pueden heredar y será una interface
funcional si cumple con las reglas anteriores
@FunctionalInterface
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Runnable {
void run();
}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Runnable {
void run();
} ✔
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface NonFunc {
boolean equals(Object obj);
}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface NonFunc {
boolean equals(Object obj);
} ✗
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Func extends NonFunc {
int compare(String o1, String o2);
}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Func extends NonFunc {
int compare(String o1, String o2);
} ✔
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Comparator<T> {
boolean equals(Object obj);
int compare(T o1, T o2);
}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Comparator<T> {
boolean equals(Object obj);
int compare(T o1, T o2);
}
✔
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Foo {
int m();
Object clone();
}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Foo {
int m();
Object clone();
}
✗
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { int m(Iterable<String> arg); }
interface Y { int m(Iterable<String> arg); }
interface Z extends X, Y {}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { int m(Iterable<String> arg); }
interface Y { int m(Iterable<String> arg); }
interface Z extends X, Y {}
✔
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { Iterable m(Iterable<String> arg); }
interface Y { Iterable<String> m(Iterable arg); }
interface Z extends X, Y {}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { Iterable m(Iterable<String> arg); }
interface Y { Iterable<String> m(Iterable arg); }
interface Z extends X, Y {}
✔
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { int m(Iterable<String> arg); }
interface Y { int m(Iterable<Integer> arg); }
interface Z extends X, Y {}
interface X<T> { void m(T arg); }
interface Y<T> { void m(T arg); }
interface Z<A, B> extends X<A>, Y<B> {}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { int m(Iterable<String> arg); }
interface Y { int m(Iterable<Integer> arg); }
interface Z extends X, Y {}
interface X<T> { void m(T arg); }
interface Y<T> { void m(T arg); }
interface Z<A, B> extends X<A>, Y<B> {}
✗
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { int m(Iterable<String> arg); }
interface Y { int m(Iterable<Integer> arg); }
interface Z extends X, Y {}
interface X<T> { void m(T arg); }
interface Y<T> { void m(T arg); }
interface Z<A, B> extends X<A>, Y<B> {}
✗
✗
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { long m(); }
interface Y { int m(); }
interface Z extends X, Y {}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface X { long m(); }
interface Y { int m(); }
interface Z extends X, Y {}
✗
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Foo<T, N extends Number> {
void m(T arg);
void m(N arg);
}
interface Bar extends Foo<String, Integer> {}
interface Baz extends Foo<Integer, Integer> {}
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Foo<T, N extends Number> {
void m(T arg);
void m(N arg);
}
interface Bar extends Foo<String, Integer> {}
interface Baz extends Foo<Integer, Integer> {}
✗
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Foo<T, N extends Number> {
void m(T arg);
void m(N arg);
}
interface Bar extends Foo<String, Integer> {}
interface Baz extends Foo<Integer, Integer> {}
✗
✗
FUNCTIONAL INTERFACE
RECONOCIENDO UNA INTERFACE FUNCIONAL
interface Foo<T, N extends Number> {
void m(T arg);
void m(N arg);
}
interface Bar extends Foo<String, Integer> {}
interface Baz extends Foo<Integer, Integer> {}
✗
✗
✔
LAMBDAS
SINTAXIS DE UNA LAMBDA
(parameters) -> expresion
(parameters) -> { statements; }
//return necesario
LAMBDAS
EJEMPLO - COMPARATOR
List<Animal> farm = loadAnimals();
Collections.sort(farm, new Comparator<Animal>() {
@Override
public int compare(Animal a1, Animal a2) {
return a1.name.compareTo(a2.name);
}
});
LAMBDAS
EJEMPLO - COMPARATOR
List<Animal> farm = loadAnimals();
Collections.sort(farm, (Animal a1, Animal a2)
-> a1.name.compareTo(a2.name));
LAMBDAS
EJEMPLO - COMPARATOR
List<Animal> farm = loadAnimals();
Collections.sort(farm, (Animal a1, Animal a2)
-> a1.name.compareTo(a2.name));
LAMBDAS
EJEMPLO - COMPARATOR
List<Animal> farm = loadAnimals();
Collections.sort(farm,
(a1, a2) -> a1.name.compareTo(a2.name));
LAMBDAS
EJEMPLOS
(int x, int y) -> x + y
(x, y) -> x - y
() -> 10
(String s) -> System.out.println(s)
x -> x * 2
c -> { int s = c.size(); c.clear(); return s; }
LAMBDAS
¿QUÉ ES UNA LAMBDA?
LAMBDAS
¿QUÉ ES UNA LAMBDA?
▸ instancias especiales de "objetos"
LAMBDAS
¿QUÉ ES UNA LAMBDA?
▸ instancias especiales de "objetos"
▸ con dependencias autocontenidas (capturadas)
LAMBDAS
¿QUÉ ES UNA LAMBDA?
▸ instancias especiales de "objetos"
▸ con dependencias autocontenidas (capturadas)
▸ diseñadas para dar soporte a la iteración interna de
colecciones
LAMBDAS
¿QUÉ ES UNA LAMBDA?
▸ instancias especiales de "objetos"
▸ con dependencias autocontenidas (capturadas)
▸ diseñadas para dar soporte a la iteración interna de
colecciones
▸ pueden ser valores de retorno
LAMBDAS
¿QUÉ ES UNA LAMBDA?
▸ instancias especiales de "objetos"
▸ con dependencias autocontenidas (capturadas)
▸ diseñadas para dar soporte a la iteración interna de
colecciones
▸ pueden ser valores de retorno
▸ pueden serializarse (mediante un cast)
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
▸ Supplier<T>
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
▸ Supplier<T>
▸ Consumer<T>
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
▸ Supplier<T>
▸ Consumer<T>
▸ Predicate<T>
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
▸ Supplier<T>
▸ Consumer<T>
▸ Predicate<T>
▸ Function<T,R>
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
▸ Supplier<T>
▸ Consumer<T>
▸ Predicate<T>
▸ Function<T,R>
▸ UnaryOperator<T>
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
▸ Supplier<T>
▸ Consumer<T>
▸ Predicate<T>
▸ Function<T,R>
▸ UnaryOperator<T>
▸ BinaryOperator<T>
LAMBDAS
INTERFACES FUNCIONALES EN JDK 8
▸ Supplier<T>
▸ Consumer<T>
▸ Predicate<T>
▸ Function<T,R>
▸ UnaryOperator<T>
▸ BinaryOperator<T>
java.util.function
LAMBDAS
Supplier<T>
LAMBDAS
Supplier<T>
▸ Representa a un proveedor de objetos tipo T
LAMBDAS
Supplier<T>
▸ Representa a un proveedor de objetos tipo T
▸ La creación del objeto T se realiza sólo hasta el momento
de utilizarse
LAMBDAS
Supplier<T>
▸ Representa a un proveedor de objetos tipo T
▸ La creación del objeto T se realiza sólo hasta el momento
de utilizarse
▸ Su método funcional es Supplier.get()
LAMBDAS
Supplier<T>
▸ Representa a un proveedor de objetos tipo T
▸ La creación del objeto T se realiza sólo hasta el momento
de utilizarse
▸ Su método funcional es Supplier.get()
logger.fine("Parámetro de búsqueda: "+parametro);
logger.fine(()->"Parámetro de búsqueda: "+parametro);
public void printOut(Supplier<String> msgSup){
if (SEND_TO_OUT)
System.out.println(msgSup.get());
}
LAMBDAS
Consumer<T>
LAMBDAS
Consumer<T>
▸ Representa una operación que acepta un único parámetro de
tipo T
LAMBDAS
Consumer<T>
▸ Representa una operación que acepta un único parámetro de
tipo T
▸ No regresa ningún resultado
LAMBDAS
Consumer<T>
▸ Representa una operación que acepta un único parámetro de
tipo T
▸ No regresa ningún resultado
▸ Se considera como una acción que produce un efecto colateral
LAMBDAS
Consumer<T>
▸ Representa una operación que acepta un único parámetro de
tipo T
▸ No regresa ningún resultado
▸ Se considera como una acción que produce un efecto colateral
▸ Su método funcional es Consumer.accept(Object)
LAMBDAS
Consumer<T>
▸ Representa una operación que acepta un único parámetro de
tipo T
▸ No regresa ningún resultado
▸ Se considera como una acción que produce un efecto colateral
▸ Su método funcional es Consumer.accept(Object)
nombres.forEach(s -> System.out.println(s));
LAMBDAS
Predicate<T>
LAMBDAS
Predicate<T>
▸ Representa un predicado booleano de un argumento
LAMBDAS
Predicate<T>
▸ Representa un predicado booleano de un argumento
▸ Su método funcional es Predicate.test(Object)
LAMBDAS
Predicate<T>
▸ Representa un predicado booleano de un argumento
▸ Su método funcional es Predicate.test(Object)
Stream<User> mayores = personas.stream().filter(
p -> p.getAge()>18);
LAMBDAS
Function<T,R>
LAMBDAS
Function<T,R>
▸ Representa una función de transformación de T a R
LAMBDAS
Function<T,R>
▸ Representa una función de transformación de T a R
▸ Regresa un objeto de tipo R
LAMBDAS
Function<T,R>
▸ Representa una función de transformación de T a R
▸ Regresa un objeto de tipo R
▸ Su método funcional es Function.apply(Object)
LAMBDAS
Function<T,R>
▸ Representa una función de transformación de T a R
▸ Regresa un objeto de tipo R
▸ Su método funcional es Function.apply(Object)
Stream<Integer> longitudes = personas
.stream()
.map(u -> u.getName()==null
? 0 : u.getName().length());
LAMBDAS
UnaryOperator<T>
LAMBDAS
UnaryOperator<T>
▸ Representa una función de transformación de T a T
LAMBDAS
UnaryOperator<T>
▸ Representa una función de transformación de T a T
▸ Su método funcional es UnaryOperator.apply(Object)
LAMBDAS
BinaryOperator<T>
LAMBDAS
BinaryOperator<T>
▸ Representa una función de Transformación de T, T a T
LAMBDAS
BinaryOperator<T>
▸ Representa una función de Transformación de T, T a T
▸ Su método funcional es BinaryOperator.apply(Object,
Object)
METHOD REFERENCES
METHOD REFERENCES
Consumer<String> consumer = s -> System.out.println(s);
Consumer<String> consumer = System.out::println;
METHOD REFERENCES
METHOD REFERENCES
▸ En algunas ocasiones sólo usamos una Lambda para llamar un
método existente









Consumer<String> consumer = s -> System.out.println(s);
Consumer<String> consumer = System.out::println;
METHOD REFERENCES
METHOD REFERENCES
▸ En algunas ocasiones sólo usamos una Lambda para llamar un
método existente









▸ Referencias a Métodos son una forma simple y fácil de leer para
implementar expresiones lambda con métodos que ya tienen nombre
Consumer<String> consumer = s -> System.out.println(s);
Consumer<String> consumer = System.out::println;
METHOD REFERENCES
TIPOS DE METHOD REFERENCES
METHOD REFERENCES
TIPOS DE METHOD REFERENCES
▸ Referencia a un método estático -
ContainingClass::staticMethodName
METHOD REFERENCES
TIPOS DE METHOD REFERENCES
▸ Referencia a un método estático -
ContainingClass::staticMethodName
▸ Referencia a un método de instancia de un objeto
específico -
containingObject::instanceMethodName
METHOD REFERENCES
TIPOS DE METHOD REFERENCES
▸ Referencia a un método estático -
ContainingClass::staticMethodName
▸ Referencia a un método de instancia de un objeto
específico -
containingObject::instanceMethodName
▸ Referencia a un método de instancia de cualquier objeto
de un tipo definido - ContainingType::methodName
METHOD REFERENCES
TIPOS DE METHOD REFERENCES
▸ Referencia a un método estático -
ContainingClass::staticMethodName
▸ Referencia a un método de instancia de un objeto
específico -
containingObject::instanceMethodName
▸ Referencia a un método de instancia de cualquier objeto
de un tipo definido - ContainingType::methodName
▸ Referencia a un constructor - ClassName::new
EJERCICIOLAMBDAS
PRIMER EJERCICIO
▸ Clonar el repositorio:





git clone https://github.com/SergioMartinezP/LambdaStream







▸ Ejercicio a resolver: EjercicioLambdas.java
OPTIONAL
Optional
OPTIONAL
Optional
▸ Contenedor de un objeto que puede o no ser null
OPTIONAL
Optional
▸ Contenedor de un objeto que puede o no ser null
▸ Si contiene un valor, isPresent() regresa true y get() el
valor
OPTIONAL
Optional
▸ Contenedor de un objeto que puede o no ser null
▸ Si contiene un valor, isPresent() regresa true y get() el
valor
▸ Es inmutable y tiene métodos para caso como: 

orElse(T) 

orElseGet(Supplier<? extends T> other) 

orElseThrow(Supplier<? extends X> 

exceptionSupplier)
STREAM API
CASO DE EJEMPLO: CALCULAR EL PROMEDIO DE EDAD DE LOS ELEGIBLES A BEBER
STREAM API
CASO DE EJEMPLO: CALCULAR EL PROMEDIO DE EDAD DE LOS ELEGIBLES A BEBER
... List<Person> list ...
double ageAverageElegibleDrivers() {
double sum = 0;
int cont = 0;
for (Person p : list) {
if (p.getAge()>=21){
sun += p.getAge();
cont++;
}
}
return sum/cont;
}
STREAM API
APLICANDO STREAMS
STREAM API
APLICANDO STREAMS
... List<Person> list ...
double ageAverageElegibleDrivers(){
return list.stream()
.filter(p -> p.age>21)
.mapToInt(p->p.getAge())
.average()
.orElse(0.0);
}
STREAM API
STREAM API
STREAM API
STREAM API
▸ Diseñado para trabajar principalmente con colecciones
STREAM API
STREAM API
▸ Diseñado para trabajar principalmente con colecciones
▸ Provee de una manera "declarativa" de procesar una
colección
STREAM API
STREAM API
▸ Diseñado para trabajar principalmente con colecciones
▸ Provee de una manera "declarativa" de procesar una
colección
▸ Se puede ver como un Iterador elegante de una colección
STREAM API
STREAM API
▸ Diseñado para trabajar principalmente con colecciones
▸ Provee de una manera "declarativa" de procesar una
colección
▸ Se puede ver como un Iterador elegante de una colección
▸ Facilita la paralelización del procesamiento de la
información
STREAM API
¿QUÉ ES UN STREAM?
STREAM API
¿QUÉ ES UN STREAM?
▸ Secuencia de elementos
STREAM API
¿QUÉ ES UN STREAM?
▸ Secuencia de elementos
▸ No almacena valores, los genera bajo demanda
STREAM API
¿QUÉ ES UN STREAM?
▸ Secuencia de elementos
▸ No almacena valores, los genera bajo demanda
▸ Fuente de datos
STREAM API
¿QUÉ ES UN STREAM?
▸ Secuencia de elementos
▸ No almacena valores, los genera bajo demanda
▸ Fuente de datos
▸ Consumen desde una fuente de datos como
Colecciones, Arreglos e I/O
STREAM API
¿QUÉ ES UN STREAM? (2)
STREAM API
¿QUÉ ES UN STREAM? (2)
▸ Operaciones de Agregación
STREAM API
¿QUÉ ES UN STREAM? (2)
▸ Operaciones de Agregación
▸ Operaciones estilo base de datos como: filter, map,
reduce, findFirst, allMatch, sorted, …
STREAM API
¿QUÉ ES UN STREAM? (2)
▸ Operaciones de Agregación
▸ Operaciones estilo base de datos como: filter, map,
reduce, findFirst, allMatch, sorted, …
▸ Encadenamiento
STREAM API
¿QUÉ ES UN STREAM? (2)
▸ Operaciones de Agregación
▸ Operaciones estilo base de datos como: filter, map,
reduce, findFirst, allMatch, sorted, …
▸ Encadenamiento
▸ La mayoría de las operaciones regresan un stream, por
lo que se pueden encadenar. El procesamiento se hace
sólo al alcanzar una operación terminal
STREAM API
¿QUÉ ES UN STREAM? (3)
STREAM API
¿QUÉ ES UN STREAM? (3)
▸ Iteración Interna
STREAM API
¿QUÉ ES UN STREAM? (3)
▸ Iteración Interna
▸ La iteración es decidida internamente y reflejará la
forma en que se encadenaron las operaciones
STREAM API
STREM VS COLLECTION
STREAM API
STREM VS COLLECTION
▸ Sin Almacenamiento
STREAM API
STREM VS COLLECTION
▸ Sin Almacenamiento
▸ Funcionales
STREAM API
STREM VS COLLECTION
▸ Sin Almacenamiento
▸ Funcionales
▸ Flojas
STREAM API
STREM VS COLLECTION
▸ Sin Almacenamiento
▸ Funcionales
▸ Flojas
▸ Posiblemente Ilimitadas
STREAM API
STREM VS COLLECTION
▸ Sin Almacenamiento
▸ Funcionales
▸ Flojas
▸ Posiblemente Ilimitadas
▸ limit(n) findFirst()
STREAM API
STREM VS COLLECTION
▸ Sin Almacenamiento
▸ Funcionales
▸ Flojas
▸ Posiblemente Ilimitadas
▸ limit(n) findFirst()
▸ Consumibles
STREAM API
PIPELINE
STREAM API
PIPELINE
▸ Fuente de datos
STREAM API
PIPELINE
▸ Fuente de datos
▸ una o varias operaciones Intermedias
STREAM API
PIPELINE
▸ Fuente de datos
▸ una o varias operaciones Intermedias
▸ Son operaciones que regresan otro stream, por lo que se pueden
encadenar, no se ejecutan sino hasta que el stream tenga una
operación terminal y deberían utilizar funciones sin efectos
colaterales
STREAM API
PIPELINE
▸ Fuente de datos
▸ una o varias operaciones Intermedias
▸ Son operaciones que regresan otro stream, por lo que se pueden
encadenar, no se ejecutan sino hasta que el stream tenga una
operación terminal y deberían utilizar funciones sin efectos
colaterales
▸ una operación Terminal
STREAM API
PIPELINE
▸ Fuente de datos
▸ una o varias operaciones Intermedias
▸ Son operaciones que regresan otro stream, por lo que se pueden
encadenar, no se ejecutan sino hasta que el stream tenga una
operación terminal y deberían utilizar funciones sin efectos
colaterales
▸ una operación Terminal
▸ Son operaciones que "Terminan" un stream, usualmente tienen
efectos colaterales e inician el procesamiento del stream y
producen un resultado
STREAM API
¿DE DÓNDE OBTENEMOS LOS STREAMS? (FUENTES)
▸ De una Colección usando los métodos stream() y
parallelStream()
▸ De un arreglo Arrays.stream(Object[])
▸ De las clases stream Stream.of(Object[]),
IntStream.range(int, int)
▸ De un archivo BufferedReader.lines()
▸ De directorios, patrones, números aleatorios y/o creadas
por nosotros
STREAM API
APLICANDO STREAMS
STREAM API
APLICANDO STREAMS
... List<Person> list ...
double ageAverageElegibleDrivers(){
return list.stream()
.filter(p -> p.age>21)
.mapToInt(p->p.getAge())
.average()
.orElse(0.0);
}
STREAM API
APLICANDO STREAMS
... List<Person> list ...
double ageAverageElegibleDrivers(){
return list.stream()
.filter(p -> p.age>21)
.mapToInt(p->p.getAge())
.average()
.orElse(0.0);
}
fuente
intermedias
terminal
STREAM API
LOS STREAMS SON OBJETOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.map(s -> s.getScore())
.max();
STREAM API
LOS STREAMS SON OBJETOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.map(s -> s.getScore())
.max();
regresa un int
STREAM API
LOS STREAMS SON OBJETOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.map(s -> s.getScore())
.max();
regresa un int
map debe envolver el int 

en un Integer
STREAM API
LOS STREAMS SON OBJETOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.map(s -> s.getScore())
.max();
regresa un int
map debe envolver el int 

en un Integer
max extrae cada Integer

para obtener el mayor
STREAM API
STREAMS DE PRIMITIVOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.mapToInt(s -> s.getScore())
.max();
STREAM API
STREAMS DE PRIMITIVOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.mapToInt(s -> s.getScore())
.max(); mapToInt produce un stream de int, 

así ya no hay boxing o unboxing
STREAM API
STREAMS DE PRIMITIVOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.mapToInt(s -> s.getScore())
.max(); mapToInt produce un stream de int, 

así ya no hay boxing o unboxing
▸ Para mejorar la eficiencia existen tres tipos de stream
primitivos
STREAM API
STREAMS DE PRIMITIVOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.mapToInt(s -> s.getScore())
.max(); mapToInt produce un stream de int, 

así ya no hay boxing o unboxing
▸ Para mejorar la eficiencia existen tres tipos de stream
primitivos
▸ IntStream, DoubleStream y LongStream
STREAM API
STREAMS DE PRIMITIVOS
int highScore = students.stream()
.filter(s -> s.gradutationYear() == 2015)
.mapToInt(s -> s.getScore())
.max(); mapToInt produce un stream de int, 

así ya no hay boxing o unboxing
▸ Para mejorar la eficiencia existen tres tipos de stream
primitivos
▸ IntStream, DoubleStream y LongStream
▸ Usar metodos como mapToInt(), mapToDouble() y
mapToLong()
STREAM API
OPERACIONES INTERMEDIAS - FUENTES
▸ generate(Supplier<T> s)
▸ Genera una secuencia infinita y desordenada de los valores
producidos por Supplier
▸ of(T t) of(T... values)
▸ Genera un stream con un solo elemento T o una secuencia de
valores T
▸ iterate(T seed, UnaryOperator<T> f)
▸ Genera una secuencia infinita producida de aplicar
iterativamente la función f(seed), f(f(seed)),…
STREAM API
OPERACIONES INTERMEDIAS - FILTRADO
▸ filter(Predicate<? super T> predicate)
▸ Regresa un stream que contiene sólo los elementos que
corresponden tras aplicar el Predicate proporcionado
▸ limit(long maxSize)
▸ Regresa un stream truncado con a lo mucho maxSize
elementos
▸ skip(long n)
▸ Regresa un stream con los elementos sobrantes tras descartar
los primeros n elementos
STREAM API
OPERACIONES INTERMEDIAS - ORDEN
▸ distinct()
▸ Regresa un stream que contiene sólo los elementos que son
diferentes aplicando un Object.equals(Object)
▸ sorted()
▸ Regresa un stream ordenado según el orden natural de los
objetos contenidos
▸ sorted(Comparator<? super T> comparator)
▸ Regresa un stream ordenado según el Comparator
proporcionado
STREAM API
OPERACIONES INTERMEDIAS - MAPEO
▸ map(Function<? super T,? extends R> mapper)
▸ Regresa un stream que contiene los resultados de
aplicar la función proporcionada a cada elemento
▸ flatMap(Function<? super T,? extends
Stream<? extends R>> mapper)
▸ Regresa un stream que reemplaza los elementos del
stream actual por los elementos del stream mapeado
▸ orders.flatMap(order ->
order.getLineItems().stream())
STREAM API
OPERACIONES INTERMEDIAS - MAPEO
Map
FlatMap
STREAM API
OPERACIONES TERMINALES - MATCH
▸ allMatch(Predicate<? super T> predicate)
▸ true si todos los elementos pasan la prueba del Predicate
▸ anyMatch(Predicate<? super T> predicate)
▸ true si alguno de los elementos pasa la prueba del
Predicate
▸ noneMatch(Predicate<? super T> predicate)
▸ true si ninguno de los elementos pasa la prueba del
Predicate
STREAM API
OPERACIONES TERMINALES - NUMÉRICOS
▸ max(Comparator<? super T> comparator)
▸ Optional del elemento mayor según comparator
▸ min(Comparator<? super T> comparator)
▸ Optional del elemento menor según comparator
▸ count()
▸ Cantidad de elementos en el stream
STREAM API
OPERACIONES TERMINALES - MÁS NUMÉRICOS
▸ Para los Streams de Primitivos IntStream, LongStream,
DoubleStream
▸ average()
▸ Obtiene el promedio de los elementos
▸ Regresa un Optional pues la lista puede estar vacía
▸ sum()
▸ Obtiene la suma de los elementos
STREAM API
OPERACIONES TERMINALES - REDUCTORES
▸ reduce(BinaryOperator<T> accumulator)
▸ Reducción de elementos de este stream usando una
función de acumulación asociativa
▸ Este acumulador toma un resultado parcial y el siguiente
elemento y regresa un resultado parcial
▸ Regresa un Optional
STREAM API
REDUCTORES
▸ Encontrar la longitud de la línea mas larga de un archivo
Path input = Paths.get("lines.txt");
int longestLineLength = Files.lines(input)
.mapToInt(String::length)
.max()
.getAsInt();
STREAM API
REDUCTORES
▸ Encontrar la longitud de la línea mas larga de un archivo
STREAM API
REDUCTORES
▸ Encontrar la longitud de la línea mas larga de un archivo
String longest = Files.lines(input)
.sort((x, y) -> y.length() - x.length())
.findFirst()
.get();
STREAM API
REDUCTORES
▸ Encontrar la longitud de la línea mas larga de un archivo
String longest = Files.lines(input)
.sort((x, y) -> y.length() - x.length())
.findFirst()
.get();
¿Y
si
el
archivo
es
muy
grande?
STREAM API
REDUCTORES - ALTERNATIVAS
▸ Usar un while y una variable que contenga el resultado
▸ simple, pero no es thread safe
▸ Usar recursión
▸ No tiene una variable mutable, por lo que es thread safe
▸ En un archivo largo podemos tener un stack overflow
▸ Usar reduce(BinaryOperator<T> accumulator)
▸ El accumulator obtiene un resultado parcial y el siguiente elemento
▸ Como con recursión, pero sin el stack overflow
STREAM API
REDUCTORES
▸ Encontrar la línea mas larga de un archivo
String longestLine = Files.lines(input)
.reduce((x, y) -> {
if (x.length() > y.length())
return x;
return y; })
.get();
STREAM API
REDUCTORES
▸ Encontrar la línea mas larga de un archivo
String longestLine = Files.lines(input)
.reduce((x, y) -> {
if (x.length() > y.length())
return x;
return y; })
.get();
La x mantiene el estado, 

en este caso guarda la linea más larga
STREAM API
OPERACIONES TERMINALES - COLECTORES
▸ collect(Collector<? super T,A,R> collector)
▸ Realiza una reducción mutable de los elementos del
stream
▸ El Contenedor del resultado puede ser un List, Map,
String, etc
▸ toArray()
▸ Regresa un Array con los elementos del Stream
STREAM API
COLLECTORS
▸ La clase Collectors implementa muchos colectores como:
▸ toList()
▸ List<String> list = people.stream()

.map(Person::getName)

.collect(Collectors.toList());
▸ toCollection(Supplier<C> collectionFactory)
▸ Set<String> set = people.stream()

.map(Person::getName).collect(

Collectors.toCollection(TreeSet::new));
STREAM API
COLLECTORS - A UN MAPA
▸ toMap(Function<? super T,? extends K> keyMapper, Function<? super
T,? extends U> valueMapper)
▸ Map<String, Student> studentIdToStudent 

students.stream()

.collect(toMap(Student::getId,

Functions.identity());
▸ toMap(Function<? super T,? extends K> keyMapper, Function<? super
T,? extends U> valueMapper, BinaryOperator<U> mergeFunction)
▸ Map<String, String> phoneBook = 

people.stream().collect(toMap(Person::getName, 

Person::getAddress, (s, a) -> s + ", " + a));
▸ Para mapas concurrentes usar toConcurrentMap(…)
STREAM API
COLLECTORS - AGRUPACIONES
▸ groupingBy(Function<? super T,? extends K> classifier)
▸ Map<Department, List<Employee>> byDept =
employees.stream().collect(

Collectors.groupingBy(Employee::getDepartment));
▸ groupingBy(Function<? super T,? extends K> classifier, Collector<?
super T,A,D> downstream)
▸ Map<City, Set<String>> namesByCity =
people.stream().collect(groupingBy(

Person::getCity, mapping(Person::getLastName,
toSet())));
▸ Para agrupaciones concurrentes usar groupingByConcurrent(…)
STREAM API
COLLECTORS - UNIENDO CADENAS
▸ Otra forma de coleccionar resultados es concatenarlos en
cadenas
▸ joining()
▸ joining(CharSequence delimiter)
▸ joining(CharSequence delimiter,
CharSequence prefix, CharSequence suffix)
String joined = things.stream()

.map(Object::toString)

.collect(Collectors.joining(", "));
STREAM API
OPERACIONES TERMINALES - ITERACIÓN
▸ Stream cuenta con métodos para iterar el stream resultante,
pero dependiendo de lo que se esté haciendo muy
probablemente alguno de los colectores anteriores lo
pueda realizar
▸ forEach(Consumer<? super T> action)
▸ Realiza la action para cada elemento en el stream
▸ forEachOrdered(Consumer<? super T> action)
▸ Realiza la action para cada elemento en el stream
garantizando el orden si se ejecuta en paralelo
EJERCICIOSTREAMS
▸ En el mismo repositorio:
▸ EjercicioStreams.java
▸ En el ejercicio 6 se requiere también completar:
▸ RandomWords.java
STREAM API
PROCESAMIENTO EN PARALELO
▸ Una "ventaja" del uso de streams es su facilidad para
convertirlas a procesos paralelos
▸ Para convertir un stream a procesamiento en paralelo sólo
hay que agregar parallel() al pipeline o usar
parallelStream() al generar el stream
▸ Basado en el framework Fork-Join
▸ Considerarlo si, y sólo si, las operaciones intermedias o
terminales a realizar son computacionalmente pesadas y
se tienen miles de elementos
GRACIAS
EN RESUMEN
▸ En Java 8 contamos con nuevas herramientas
▸ Lambdas - Funciones independientes para realizar
tareas muy específicas
▸ Optional - Forma de manejar la incertidumbre
▸ Streams - Forma de procesar colecciones o secuencias
de valores

Más contenido relacionado

La actualidad más candente

PROBLEMAS DE POGRAMACION 1
PROBLEMAS DE POGRAMACION 1PROBLEMAS DE POGRAMACION 1
PROBLEMAS DE POGRAMACION 1Jordan Puente
 
Programando con Python
Programando con PythonProgramando con Python
Programando con PythonMario IC
 
Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)
Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)
Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)José Antonio Sandoval Acosta
 
Practicas segundo parcial de programacion avanzada
Practicas segundo parcial de programacion avanzadaPracticas segundo parcial de programacion avanzada
Practicas segundo parcial de programacion avanzadaDariio Lopezz Young
 
Unidad2 programas while , do while y for
Unidad2 programas while , do while  y forUnidad2 programas while , do while  y for
Unidad2 programas while , do while y forMiguel Angel Peña
 
Ejemplos de algoritmos en C básicos (aprendiendo a programar)
Ejemplos de algoritmos en C básicos (aprendiendo a programar)Ejemplos de algoritmos en C básicos (aprendiendo a programar)
Ejemplos de algoritmos en C básicos (aprendiendo a programar)Kiim Kerrigan
 
Lenguaje C
Lenguaje CLenguaje C
Lenguaje Cfior
 
Lenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuario
Lenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuarioLenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuario
Lenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuarioCarlos
 
Ejercicios sencillos en c
Ejercicios sencillos en cEjercicios sencillos en c
Ejercicios sencillos en cAlma Navarro
 
Factura en borland c++
Factura en borland c++Factura en borland c++
Factura en borland c++Luis Coba
 
Codificaciones c++
Codificaciones c++Codificaciones c++
Codificaciones c++mario_10
 
Ejercicios de programacion en c++
Ejercicios de programacion en c++Ejercicios de programacion en c++
Ejercicios de programacion en c++Tony Pesantez
 
Unidad vi esp parte 2 procesimientos en plsql y transact sql
Unidad vi esp parte 2 procesimientos en plsql y transact sqlUnidad vi esp parte 2 procesimientos en plsql y transact sql
Unidad vi esp parte 2 procesimientos en plsql y transact sqlTitiushko Jazz
 
Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.
Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.
Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.erick llerena
 

La actualidad más candente (19)

PROBLEMAS DE POGRAMACION 1
PROBLEMAS DE POGRAMACION 1PROBLEMAS DE POGRAMACION 1
PROBLEMAS DE POGRAMACION 1
 
Acciones funciones
Acciones funcionesAcciones funciones
Acciones funciones
 
Programando con Python
Programando con PythonProgramando con Python
Programando con Python
 
Divisores de un número (código Dev C++)
Divisores de un número (código Dev C++)Divisores de un número (código Dev C++)
Divisores de un número (código Dev C++)
 
algitmos clases
algitmos clasesalgitmos clases
algitmos clases
 
Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)
Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)
Algorimos básicos para cifrar y descifrar en C# (encriptar y desencriptar)
 
Practicas segundo parcial de programacion avanzada
Practicas segundo parcial de programacion avanzadaPracticas segundo parcial de programacion avanzada
Practicas segundo parcial de programacion avanzada
 
Unidad2 programas while , do while y for
Unidad2 programas while , do while  y forUnidad2 programas while , do while  y for
Unidad2 programas while , do while y for
 
Ejemplos de algoritmos en C básicos (aprendiendo a programar)
Ejemplos de algoritmos en C básicos (aprendiendo a programar)Ejemplos de algoritmos en C básicos (aprendiendo a programar)
Ejemplos de algoritmos en C básicos (aprendiendo a programar)
 
Lenguaje C
Lenguaje CLenguaje C
Lenguaje C
 
Lenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuario
Lenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuarioLenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuario
Lenguajesdeprogramacion c nivel1-unidad1-03-funciones definidas por el usuario
 
Funciones en C
Funciones en CFunciones en C
Funciones en C
 
Ejercicios sencillos en c
Ejercicios sencillos en cEjercicios sencillos en c
Ejercicios sencillos en c
 
Factura en borland c++
Factura en borland c++Factura en borland c++
Factura en borland c++
 
Codificaciones c++
Codificaciones c++Codificaciones c++
Codificaciones c++
 
Ejercicios de programacion en c++
Ejercicios de programacion en c++Ejercicios de programacion en c++
Ejercicios de programacion en c++
 
Unidad vi esp parte 2 procesimientos en plsql y transact sql
Unidad vi esp parte 2 procesimientos en plsql y transact sqlUnidad vi esp parte 2 procesimientos en plsql y transact sql
Unidad vi esp parte 2 procesimientos en plsql y transact sql
 
FUNCIONES LENGUAJE C
FUNCIONES LENGUAJE CFUNCIONES LENGUAJE C
FUNCIONES LENGUAJE C
 
Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.
Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.
Ejercicios de Aplicación de las Instrucciones de Entrada y Salida.
 

Similar a Lambda & Stream API workshop 2019

Similar a Lambda & Stream API workshop 2019 (12)

Java Basico
Java BasicoJava Basico
Java Basico
 
Primitive Obsession. FrontFest 2020
Primitive Obsession. FrontFest 2020Primitive Obsession. FrontFest 2020
Primitive Obsession. FrontFest 2020
 
Unidad vi esp parte 2 procesimientos en plsql y transact sql
Unidad vi esp parte 2 procesimientos en plsql y transact sqlUnidad vi esp parte 2 procesimientos en plsql y transact sql
Unidad vi esp parte 2 procesimientos en plsql y transact sql
 
Ejemploc de caso
Ejemploc de casoEjemploc de caso
Ejemploc de caso
 
Practicas de programacion 11 20
Practicas de programacion 11 20Practicas de programacion 11 20
Practicas de programacion 11 20
 
Codigo ejercicios
Codigo ejerciciosCodigo ejercicios
Codigo ejercicios
 
Scrip de la base de datos cine
Scrip de la base de datos cineScrip de la base de datos cine
Scrip de la base de datos cine
 
Hechos en clase
Hechos en claseHechos en clase
Hechos en clase
 
Dart como alternativa a TypeScript (Codemotion 2016)
Dart como alternativa a TypeScript (Codemotion 2016)Dart como alternativa a TypeScript (Codemotion 2016)
Dart como alternativa a TypeScript (Codemotion 2016)
 
Ruby
RubyRuby
Ruby
 
Practicas c++
Practicas c++Practicas c++
Practicas c++
 
Practicas c++
Practicas c++Practicas c++
Practicas c++
 

Más de superserch

Identificando problemas en el JVM
Identificando problemas en el JVMIdentificando problemas en el JVM
Identificando problemas en el JVMsuperserch
 
Introducción al manejo de memoria en el JVM
Introducción al manejo de memoria en el JVMIntroducción al manejo de memoria en el JVM
Introducción al manejo de memoria en el JVMsuperserch
 
OWASP Top 10 2017
OWASP Top 10 2017OWASP Top 10 2017
OWASP Top 10 2017superserch
 
Garbage Collection en el JVM
Garbage Collection en el JVMGarbage Collection en el JVM
Garbage Collection en el JVMsuperserch
 
Jvmmx docker jvm
Jvmmx docker jvmJvmmx docker jvm
Jvmmx docker jvmsuperserch
 
Cloudino workshopcpmx7
Cloudino workshopcpmx7Cloudino workshopcpmx7
Cloudino workshopcpmx7superserch
 
Chela stress test
Chela stress testChela stress test
Chela stress testsuperserch
 
Zed Attack Proxy
Zed Attack ProxyZed Attack Proxy
Zed Attack Proxysuperserch
 
Inyección, XSS, CSRF en ChelaJS
Inyección, XSS, CSRF en ChelaJSInyección, XSS, CSRF en ChelaJS
Inyección, XSS, CSRF en ChelaJSsuperserch
 

Más de superserch (10)

Identificando problemas en el JVM
Identificando problemas en el JVMIdentificando problemas en el JVM
Identificando problemas en el JVM
 
Introducción al manejo de memoria en el JVM
Introducción al manejo de memoria en el JVMIntroducción al manejo de memoria en el JVM
Introducción al manejo de memoria en el JVM
 
OWASP Top 10 2017
OWASP Top 10 2017OWASP Top 10 2017
OWASP Top 10 2017
 
Garbage Collection en el JVM
Garbage Collection en el JVMGarbage Collection en el JVM
Garbage Collection en el JVM
 
Jvmmx docker jvm
Jvmmx docker jvmJvmmx docker jvm
Jvmmx docker jvm
 
Cloudino workshopcpmx7
Cloudino workshopcpmx7Cloudino workshopcpmx7
Cloudino workshopcpmx7
 
Jvmmx jigsaw
Jvmmx jigsawJvmmx jigsaw
Jvmmx jigsaw
 
Chela stress test
Chela stress testChela stress test
Chela stress test
 
Zed Attack Proxy
Zed Attack ProxyZed Attack Proxy
Zed Attack Proxy
 
Inyección, XSS, CSRF en ChelaJS
Inyección, XSS, CSRF en ChelaJSInyección, XSS, CSRF en ChelaJS
Inyección, XSS, CSRF en ChelaJS
 

Último

MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxMacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxcalzadillasluis134
 
Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.CZSOTEC
 
Webinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfWebinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfAnaRosaMontenegro
 
Tipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógicoTipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógicoMaxCaldern2
 
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Neo4j
 
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...FabianCruz73
 
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...Neo4j
 
Delitos informáticos en Slideshare.pptx
Delitos informáticos en  Slideshare.pptxDelitos informáticos en  Slideshare.pptx
Delitos informáticos en Slideshare.pptxmaykolmagallanes012
 
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOSISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOELIAMARYTOVARFLOREZD
 
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosBBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosNeo4j
 
SQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptxSQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptxRAMIROANTONIOGALINDO
 

Último (11)

MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxMacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
 
Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.
 
Webinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfWebinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdf
 
Tipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógicoTipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógico
 
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
 
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
 
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
 
Delitos informáticos en Slideshare.pptx
Delitos informáticos en  Slideshare.pptxDelitos informáticos en  Slideshare.pptx
Delitos informáticos en Slideshare.pptx
 
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOSISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
 
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosBBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
 
SQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptxSQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptx
 

Lambda & Stream API workshop 2019

  • 1. LAMBDAS & STREAM API JAVA 8 @SuperSerch
  • 2. INTRODUCCIÓN ¿POR QUÉ TENER LAMBDAS Y STREAMS? ▸ Facilitar la programación concurrente ▸ Reducir los errores al programar iteraciones de colecciones
  • 3. CASO DE EJEMPLO PERSON class Person { int getAge(); Sex getSex(); PhoneNumber getPhoneNumber(); EmailAddr getEmailAddr(); PostalAddr getPostalAddr(); ... } enum Sex { FEMALE, MALE }
  • 4. CASO DE EJEMPLO ROBOCALL - PERSONAS EN EDAD DE CONDUCIR class MyApplication { List<Person> list = ... void robocallEligibleDrivers() { ... } ... }
  • 5. CASO DE EJEMPLO ROBOCALL - PERSONAS EN EDAD DE CONDUCIR void robocallEligibleDrivers() { for (Person p : list) { if (p.getAge()>=16){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 6. CASO DE EJEMPLO ROBOCALL - PERSONAS EN EDAD DE VOTAR
  • 7. CASO DE EJEMPLO ROBOCALL - PERSONAS EN EDAD DE VOTAR void robocallEligibleVoters() { for (Person p : list) { if (p.getAge()>=18){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 8. CASO DE EJEMPLO ROBOCALL - PERSONAS EN EDAD DE BEBER
  • 9. CASO DE EJEMPLO ROBOCALL - PERSONAS EN EDAD DE BEBER void robocallEligibleDrinkers() { for (Person p : list) { if (p.getAge()>=21){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 10. CASO DE EJEMPLO ROBOCALL - PERSONAS EN EDAD DE BEBER void robocallEligibleDrinkers() { for (Person p : list) { if (p.getAge()>=21){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } } CÓDIGO REPETIDO
  • 11. CASO DE EJEMPLO SOLUCIÓN PARAMETRIZAR!
  • 12. CASO DE EJEMPLO SOLUCIÓN PARAMETRIZAR! void robocallOlderThan(int age) { for (Person p : list) { if (p.getAge()>=age){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 13. CASO DE EJEMPLO USANDO PARÁMETROS void robocallEligibleDrivers() { robocallOlderThan(16); } void robocallEligibleVoters() { robocallOlderThan(18); } void robocallEligibleDrinkers() { robocallOlderThan(21); }
  • 14. CASO DE EJEMPLO CAMBIAN LOS REQUERIMIENTOS ▸ Enviar publicidad a potenciales pilotos comerciales ▸ edad mínima de 23 ▸ pero retiro mandatorio a los 65 ▸ Agregamos otro parámetro y ahora buscamos rangos ▸ usamos Integer.MAX_VALUE para el tope superior si sólo tenemos el límite inferior ▸ usamos 0 para el tope inferior si sólo tenemos el límite superior
  • 15. CASO DE EJEMPLO CON RANGO DE EDAD void robocallAgeRange(int low, int high) { for (Person p : list) { if (low <= p.getAge() && p.getAge() < high){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 16. CASO DE EJEMPLO USANDO RANGO DE EDAD void robocallEligiblePilots() { robocallAgeRange(23, 65); } void robocallEligibleDrivers() { robocallAgeRange(16, Integer.MAX_VALUE); } void robocallEligibleVoters() { robocallAgeRange(18, Integer.MAX_VALUE); } void robocallEligibleDrinkers() { robocallAgeRange(21, Integer.MAX_VALUE); }
  • 17. CASO DE EJEMPLO UN REQUERIMIENTO MÁS ▸ Enviar publicidad a obligados a cumplir servicio militar ▸ con edades entre 18 y 26 ▸ sólo hombres
  • 18. CASO DE EJEMPLO UN REQUERIMIENTO MÁS ▸ Enviar publicidad a obligados a cumplir servicio militar ▸ con edades entre 18 y 26 ▸ sólo hombres void robocallSelectiveService() { robocallSexAgeRange(Sex.MALE, 18, 26); }
  • 19. CASO DE EJEMPLO CON SEXO Y RANGO DE EDAD void robocallSexAgeRange(Sex sex, int low, int high) { for (Person p : list) { if (p.getSex() == sex && low <= p.getAge() && p.getAge() < high){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 20. CASO DE EJEMPLO PERO AL COLOCARLO EN LOS CASOS PREVIOS void robocallEligiblePilots() { robocallSexAgeRange(???, 23, 65); } void robocallEligibleDrivers() { robocallSexAgeRange(???, 16, Integer.MAX_VALUE); } void robocallEligibleVoters() { robocallSexAgeRange(???, 18, Integer.MAX_VALUE); } void robocallEligibleDrinkers() { robocallSexAgeRange(???, 21, Integer.MAX_VALUE); }
  • 21. CASO DE EJEMPLO PERO AL COLOCARLO EN LOS CASOS PREVIOS void robocallEligiblePilots() { robocallSexAgeRange(???, 23, 65); } void robocallEligibleDrivers() { robocallSexAgeRange(???, 16, Integer.MAX_VALUE); } void robocallEligibleVoters() { robocallSexAgeRange(???, 18, Integer.MAX_VALUE); } void robocallEligibleDrinkers() { robocallSexAgeRange(???, 21, Integer.MAX_VALUE); }
  • 22. CASO DE EJEMPLO INTENTO #1 DE ARREGLARLO enum Sex { FEMALE, MALE, DONT_CARE } void robocallSexAgeRange(Sex sex, int low, int high) { for (Person p : list) { if ((sex == DONT_CARE || p.getSex() == sex) && low <= p.getAge() && p.getAge() < high){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 23. CASO DE EJEMPLO INTENTO #1 DE ARREGLARLO enum Sex { FEMALE, MALE, DONT_CARE } void robocallSexAgeRange(Sex sex, int low, int high) { for (Person p : list) { if ((sex == DONT_CARE || p.getSex() == sex) && low <= p.getAge() && p.getAge() < high){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 24. CASO DE EJEMPLO INTENTO #1 DE ARREGLARLO enum Sex { FEMALE, MALE, DONT_CARE } void robocallSexAgeRange(Sex sex, int low, int high) { for (Person p : list) { if ((sex == DONT_CARE || p.getSex() == sex) && low <= p.getAge() && p.getAge() < high){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } } IMPLEMENTACIÓN CONTAMINA EL MODELO
  • 25. CASO DE EJEMPLO INTENTO #2 DE ARREGLARLO - USAR NULL void robocallSexAgeRange(Sex sex, int low, int high) { for (Person p : list) { if ((sex == null || p.getSex() == sex) && low <= p.getAge() && p.getAge() < high){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 26. CASO DE EJEMPLO AL COLOCARLO EN LOS CASOS PREVIOS void robocallSelectiveService() { robocallSexAgeRange(Sex.MALE, 18, 26); } void robocallEligiblePilots() { robocallSexAgeRange(null, 23, 65); } void robocallEligibleDrivers() { robocallSexAgeRange(null, 16, Integer.MAX_VALUE); }
  • 27. CASO DE EJEMPLO AL COLOCARLO EN LOS CASOS PREVIOS void robocallSelectiveService() { robocallSexAgeRange(Sex.MALE, 18, 26); } void robocallEligiblePilots() { robocallSexAgeRange(null, 23, 65); } void robocallEligibleDrivers() { robocallSexAgeRange(null, 16, Integer.MAX_VALUE); } ▸ Pero, ¿y si sex==null significa que no se capturó el sexo?
  • 28. CASO DE EJEMPLO INTENTO #3 AGREGAR UN BOOLEAN void robocallSexAgeRange(Sex sex, boolean checkSex, int low, int high) { for (Person p : list) { if ((!checkSex || p.getSex() == sex) && low <= p.getAge() && p.getAge() < high){ Phonenumber num = p.getPhoneNumber(); robocall(num); } } }
  • 29. CASO DE EJEMPLO AL COLOCARLO EN LOS CASOS PREVIOS void robocallSelectiveService() { robocallSexAgeRange(Sex.MALE, true, 18, 26); } void robocallEligiblePilots() { robocallSexAgeRange(null, false, 23, 65); } void robocallEligibleDrivers() { robocallSexAgeRange(Sex.MALE, false, 16, Integer.MAX_VALUE); }
  • 30. CASO DE EJEMPLO AL COLOCARLO EN LOS CASOS PREVIOS void robocallSelectiveService() { robocallSexAgeRange(Sex.MALE, true, 18, 26); } void robocallEligiblePilots() { robocallSexAgeRange(null, false, 23, 65); } void robocallEligibleDrivers() { robocallSexAgeRange(Sex.MALE, false, 16, Integer.MAX_VALUE); } ▸ aún hay que poner algo en el campo de sex, incluso si es ignorado
  • 31. CASO DE EJEMPLO AL COLOCARLO EN LOS CASOS PREVIOS void robocallSelectiveService() { robocallSexAgeRange(Sex.MALE, true, 18, 26); } void robocallEligiblePilots() { robocallSexAgeRange(null, false, 23, 65); } void robocallEligibleDrivers() { robocallSexAgeRange(Sex.MALE, false, 16, Integer.MAX_VALUE); } ▸ aún hay que poner algo en el campo de sex, incluso si es ignorado ▸ ¿Y si olvidamos cambiar el boolean al cambiar la llamada?
  • 32. CASO DE EJEMPLO LO QUE EL CALLER QUIERE void robocallSelectiveService() { robocallMatchingPersons(*******) }
  • 33. CASO DE EJEMPLO LO QUE EL CALLER QUIERE void robocallSelectiveService() { robocallMatchingPersons(*******) } ▸ *** dada una persona, usando características de la persona, decidir cuando esa persona deberá ser robo-llamada
  • 34. CASO DE EJEMPLO LO QUE LA BIBLIOTECA QUIERE void robocallMatchingPersons(********) { for (Person p : list) { if (***) { PhoneNumber num = p.getPhoneNumber(); robocall(num); } } }
  • 35. CASO DE EJEMPLO LO QUE LA BIBLIOTECA QUIERE void robocallMatchingPersons(********) { for (Person p : list) { if (***) { PhoneNumber num = p.getPhoneNumber(); robocall(num); } } }
  • 36. CASO DE EJEMPLO LO QUE LA BIBLIOTECA QUIERE void robocallMatchingPersons(********) { for (Person p : list) { if (***) { PhoneNumber num = p.getPhoneNumber(); robocall(num); } } } ES UNA FUNCIÓN!
  • 37. CASO DE EJEMPLO LO QUE LA BIBLIOTECA QUIERE void robocallMatchingPersons(********) { for (Person p : list) { if (***) { PhoneNumber num = p.getPhoneNumber(); robocall(num); } } } ES UNA FUNCIÓN! ▸ Función dada una persona, usando características de la persona, decidir cuando esa persona deberá ser robo-llamada ▸ El parámetro de esa función es una Persona ▸ El resultado de esa función es un boolean
  • 38. LAMBDAS ¿QUÉ ES UNA EXPRESIÓN LAMBDA? λ
  • 39. LAMBDAS ¿QUÉ ES UNA EXPRESIÓN LAMBDA? ▸ Forma matemática que define la transformación de un valor λ
  • 40. LAMBDAS ¿QUÉ ES UNA EXPRESIÓN LAMBDA? ▸ Forma matemática que define la transformación de un valor ▸ A las cosas que realizan transformaciones las denominamos Funciones λ
  • 41. LAMBDAS ¿QUÉ ES UNA EXPRESIÓN LAMBDA? ▸ Forma matemática que define la transformación de un valor ▸ A las cosas que realizan transformaciones las denominamos Funciones ▸ int -> int 
 Función que transforma de entero a entero λ
  • 42. LAMBDAS ¿QUÉ ES UNA EXPRESIÓN LAMBDA? ▸ Forma matemática que define la transformación de un valor ▸ A las cosas que realizan transformaciones las denominamos Funciones ▸ int -> int 
 Función que transforma de entero a entero ▸ Las expresiones Lambda son la manera de agregar funciones a Java λ
  • 43. LAMBDAS PROPÓSITO DE LAS EXPRESIONES LAMBDA
  • 44. LAMBDAS PROPÓSITO DE LAS EXPRESIONES LAMBDA ▸ Proveen una manera sencilla para distribuir procesamiento específico
  • 45. LAMBDAS PROPÓSITO DE LAS EXPRESIONES LAMBDA ▸ Proveen una manera sencilla para distribuir procesamiento específico ▸ Útiles para procesar colecciones
  • 46. LAMBDAS PROPÓSITO DE LAS EXPRESIONES LAMBDA ▸ Proveen una manera sencilla para distribuir procesamiento específico ▸ Útiles para procesar colecciones ▸ Facilitar la cooperación entre desarrolladores y usuarios de bibliotecas
  • 47. LAMBDAS PROPÓSITO DE LAS EXPRESIONES LAMBDA ▸ Proveen una manera sencilla para distribuir procesamiento específico ▸ Útiles para procesar colecciones ▸ Facilitar la cooperación entre desarrolladores y usuarios de bibliotecas ▸ (T p, T2 q, …) -> {bloque de código}
  • 48. LAMBDAS ¿CÓMO REPRESENTAMOS FUNCIONES EN JAVA? new Thread(new Runnable() { public void run() { System.out.println("Estoy en otro hilo."); } }).start(); Collections.sort(people, new Comparator<Person>() { public int compare(Person x, Person y) { return x.getLastName().compareTo(y.getLastName()); } });
  • 51. LAMBDAS LAMBDAS ▸ Bloque de código ▸ Se basan en Target Typing (Según el contexto se determina el tipo de la Lambda)
  • 52. LAMBDAS LAMBDAS ▸ Bloque de código ▸ Se basan en Target Typing (Según el contexto se determina el tipo de la Lambda) ▸ existen en dos categorías:
  • 53. LAMBDAS LAMBDAS ▸ Bloque de código ▸ Se basan en Target Typing (Según el contexto se determina el tipo de la Lambda) ▸ existen en dos categorías: ▸ Sin efectos colaterales
  • 54. LAMBDAS LAMBDAS ▸ Bloque de código ▸ Se basan en Target Typing (Según el contexto se determina el tipo de la Lambda) ▸ existen en dos categorías: ▸ Sin efectos colaterales ▸ Con efectos colaterales
  • 55. LAMBDAS LAMBDAS ▸ Bloque de código ▸ Se basan en Target Typing (Según el contexto se determina el tipo de la Lambda) ▸ existen en dos categorías: ▸ Sin efectos colaterales ▸ Con efectos colaterales ▸ Siempre asignadas a una Functional Interface
  • 57. FUNCTIONAL INTERFACE FUNCTIONAL INTERFACE ▸ Interfaces que tienen sólo un método abstracto. @FunctionalInterface
  • 58. FUNCTIONAL INTERFACE FUNCTIONAL INTERFACE ▸ Interfaces que tienen sólo un método abstracto. ▸ Los métodos por defecto, dado que ya están implementados, no cuentan para definir si una Interface es funcional o no @FunctionalInterface
  • 59. FUNCTIONAL INTERFACE FUNCTIONAL INTERFACE ▸ Interfaces que tienen sólo un método abstracto. ▸ Los métodos por defecto, dado que ya están implementados, no cuentan para definir si una Interface es funcional o no ▸ Si la interface declara un método abstracto, pero que sobreescribe un método de java.lang.Object, este tampoco cuenta para definir si es funcional o no @FunctionalInterface
  • 60. FUNCTIONAL INTERFACE FUNCTIONAL INTERFACE ▸ Interfaces que tienen sólo un método abstracto. ▸ Los métodos por defecto, dado que ya están implementados, no cuentan para definir si una Interface es funcional o no ▸ Si la interface declara un método abstracto, pero que sobreescribe un método de java.lang.Object, este tampoco cuenta para definir si es funcional o no ▸ Multiples Interfaces se pueden heredar y será una interface funcional si cumple con las reglas anteriores @FunctionalInterface
  • 61. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Runnable { void run(); }
  • 62. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Runnable { void run(); } ✔
  • 63. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface NonFunc { boolean equals(Object obj); }
  • 64. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface NonFunc { boolean equals(Object obj); } ✗
  • 65. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Func extends NonFunc { int compare(String o1, String o2); }
  • 66. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Func extends NonFunc { int compare(String o1, String o2); } ✔
  • 67. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Comparator<T> { boolean equals(Object obj); int compare(T o1, T o2); }
  • 68. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Comparator<T> { boolean equals(Object obj); int compare(T o1, T o2); } ✔
  • 69. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Foo { int m(); Object clone(); }
  • 70. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Foo { int m(); Object clone(); } ✗
  • 71. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { int m(Iterable<String> arg); } interface Y { int m(Iterable<String> arg); } interface Z extends X, Y {}
  • 72. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { int m(Iterable<String> arg); } interface Y { int m(Iterable<String> arg); } interface Z extends X, Y {} ✔
  • 73. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { Iterable m(Iterable<String> arg); } interface Y { Iterable<String> m(Iterable arg); } interface Z extends X, Y {}
  • 74. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { Iterable m(Iterable<String> arg); } interface Y { Iterable<String> m(Iterable arg); } interface Z extends X, Y {} ✔
  • 75. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { int m(Iterable<String> arg); } interface Y { int m(Iterable<Integer> arg); } interface Z extends X, Y {} interface X<T> { void m(T arg); } interface Y<T> { void m(T arg); } interface Z<A, B> extends X<A>, Y<B> {}
  • 76. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { int m(Iterable<String> arg); } interface Y { int m(Iterable<Integer> arg); } interface Z extends X, Y {} interface X<T> { void m(T arg); } interface Y<T> { void m(T arg); } interface Z<A, B> extends X<A>, Y<B> {} ✗
  • 77. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { int m(Iterable<String> arg); } interface Y { int m(Iterable<Integer> arg); } interface Z extends X, Y {} interface X<T> { void m(T arg); } interface Y<T> { void m(T arg); } interface Z<A, B> extends X<A>, Y<B> {} ✗ ✗
  • 78. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { long m(); } interface Y { int m(); } interface Z extends X, Y {}
  • 79. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface X { long m(); } interface Y { int m(); } interface Z extends X, Y {} ✗
  • 80. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Foo<T, N extends Number> { void m(T arg); void m(N arg); } interface Bar extends Foo<String, Integer> {} interface Baz extends Foo<Integer, Integer> {}
  • 81. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Foo<T, N extends Number> { void m(T arg); void m(N arg); } interface Bar extends Foo<String, Integer> {} interface Baz extends Foo<Integer, Integer> {} ✗
  • 82. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Foo<T, N extends Number> { void m(T arg); void m(N arg); } interface Bar extends Foo<String, Integer> {} interface Baz extends Foo<Integer, Integer> {} ✗ ✗
  • 83. FUNCTIONAL INTERFACE RECONOCIENDO UNA INTERFACE FUNCIONAL interface Foo<T, N extends Number> { void m(T arg); void m(N arg); } interface Bar extends Foo<String, Integer> {} interface Baz extends Foo<Integer, Integer> {} ✗ ✗ ✔
  • 84. LAMBDAS SINTAXIS DE UNA LAMBDA (parameters) -> expresion (parameters) -> { statements; } //return necesario
  • 85. LAMBDAS EJEMPLO - COMPARATOR List<Animal> farm = loadAnimals(); Collections.sort(farm, new Comparator<Animal>() { @Override public int compare(Animal a1, Animal a2) { return a1.name.compareTo(a2.name); } });
  • 86. LAMBDAS EJEMPLO - COMPARATOR List<Animal> farm = loadAnimals(); Collections.sort(farm, (Animal a1, Animal a2) -> a1.name.compareTo(a2.name));
  • 87. LAMBDAS EJEMPLO - COMPARATOR List<Animal> farm = loadAnimals(); Collections.sort(farm, (Animal a1, Animal a2) -> a1.name.compareTo(a2.name));
  • 88. LAMBDAS EJEMPLO - COMPARATOR List<Animal> farm = loadAnimals(); Collections.sort(farm, (a1, a2) -> a1.name.compareTo(a2.name));
  • 89. LAMBDAS EJEMPLOS (int x, int y) -> x + y (x, y) -> x - y () -> 10 (String s) -> System.out.println(s) x -> x * 2 c -> { int s = c.size(); c.clear(); return s; }
  • 91. LAMBDAS ¿QUÉ ES UNA LAMBDA? ▸ instancias especiales de "objetos"
  • 92. LAMBDAS ¿QUÉ ES UNA LAMBDA? ▸ instancias especiales de "objetos" ▸ con dependencias autocontenidas (capturadas)
  • 93. LAMBDAS ¿QUÉ ES UNA LAMBDA? ▸ instancias especiales de "objetos" ▸ con dependencias autocontenidas (capturadas) ▸ diseñadas para dar soporte a la iteración interna de colecciones
  • 94. LAMBDAS ¿QUÉ ES UNA LAMBDA? ▸ instancias especiales de "objetos" ▸ con dependencias autocontenidas (capturadas) ▸ diseñadas para dar soporte a la iteración interna de colecciones ▸ pueden ser valores de retorno
  • 95. LAMBDAS ¿QUÉ ES UNA LAMBDA? ▸ instancias especiales de "objetos" ▸ con dependencias autocontenidas (capturadas) ▸ diseñadas para dar soporte a la iteración interna de colecciones ▸ pueden ser valores de retorno ▸ pueden serializarse (mediante un cast)
  • 97. LAMBDAS INTERFACES FUNCIONALES EN JDK 8 ▸ Supplier<T>
  • 98. LAMBDAS INTERFACES FUNCIONALES EN JDK 8 ▸ Supplier<T> ▸ Consumer<T>
  • 99. LAMBDAS INTERFACES FUNCIONALES EN JDK 8 ▸ Supplier<T> ▸ Consumer<T> ▸ Predicate<T>
  • 100. LAMBDAS INTERFACES FUNCIONALES EN JDK 8 ▸ Supplier<T> ▸ Consumer<T> ▸ Predicate<T> ▸ Function<T,R>
  • 101. LAMBDAS INTERFACES FUNCIONALES EN JDK 8 ▸ Supplier<T> ▸ Consumer<T> ▸ Predicate<T> ▸ Function<T,R> ▸ UnaryOperator<T>
  • 102. LAMBDAS INTERFACES FUNCIONALES EN JDK 8 ▸ Supplier<T> ▸ Consumer<T> ▸ Predicate<T> ▸ Function<T,R> ▸ UnaryOperator<T> ▸ BinaryOperator<T>
  • 103. LAMBDAS INTERFACES FUNCIONALES EN JDK 8 ▸ Supplier<T> ▸ Consumer<T> ▸ Predicate<T> ▸ Function<T,R> ▸ UnaryOperator<T> ▸ BinaryOperator<T> java.util.function
  • 105. LAMBDAS Supplier<T> ▸ Representa a un proveedor de objetos tipo T
  • 106. LAMBDAS Supplier<T> ▸ Representa a un proveedor de objetos tipo T ▸ La creación del objeto T se realiza sólo hasta el momento de utilizarse
  • 107. LAMBDAS Supplier<T> ▸ Representa a un proveedor de objetos tipo T ▸ La creación del objeto T se realiza sólo hasta el momento de utilizarse ▸ Su método funcional es Supplier.get()
  • 108. LAMBDAS Supplier<T> ▸ Representa a un proveedor de objetos tipo T ▸ La creación del objeto T se realiza sólo hasta el momento de utilizarse ▸ Su método funcional es Supplier.get() logger.fine("Parámetro de búsqueda: "+parametro); logger.fine(()->"Parámetro de búsqueda: "+parametro); public void printOut(Supplier<String> msgSup){ if (SEND_TO_OUT) System.out.println(msgSup.get()); }
  • 110. LAMBDAS Consumer<T> ▸ Representa una operación que acepta un único parámetro de tipo T
  • 111. LAMBDAS Consumer<T> ▸ Representa una operación que acepta un único parámetro de tipo T ▸ No regresa ningún resultado
  • 112. LAMBDAS Consumer<T> ▸ Representa una operación que acepta un único parámetro de tipo T ▸ No regresa ningún resultado ▸ Se considera como una acción que produce un efecto colateral
  • 113. LAMBDAS Consumer<T> ▸ Representa una operación que acepta un único parámetro de tipo T ▸ No regresa ningún resultado ▸ Se considera como una acción que produce un efecto colateral ▸ Su método funcional es Consumer.accept(Object)
  • 114. LAMBDAS Consumer<T> ▸ Representa una operación que acepta un único parámetro de tipo T ▸ No regresa ningún resultado ▸ Se considera como una acción que produce un efecto colateral ▸ Su método funcional es Consumer.accept(Object) nombres.forEach(s -> System.out.println(s));
  • 116. LAMBDAS Predicate<T> ▸ Representa un predicado booleano de un argumento
  • 117. LAMBDAS Predicate<T> ▸ Representa un predicado booleano de un argumento ▸ Su método funcional es Predicate.test(Object)
  • 118. LAMBDAS Predicate<T> ▸ Representa un predicado booleano de un argumento ▸ Su método funcional es Predicate.test(Object) Stream<User> mayores = personas.stream().filter( p -> p.getAge()>18);
  • 120. LAMBDAS Function<T,R> ▸ Representa una función de transformación de T a R
  • 121. LAMBDAS Function<T,R> ▸ Representa una función de transformación de T a R ▸ Regresa un objeto de tipo R
  • 122. LAMBDAS Function<T,R> ▸ Representa una función de transformación de T a R ▸ Regresa un objeto de tipo R ▸ Su método funcional es Function.apply(Object)
  • 123. LAMBDAS Function<T,R> ▸ Representa una función de transformación de T a R ▸ Regresa un objeto de tipo R ▸ Su método funcional es Function.apply(Object) Stream<Integer> longitudes = personas .stream() .map(u -> u.getName()==null ? 0 : u.getName().length());
  • 125. LAMBDAS UnaryOperator<T> ▸ Representa una función de transformación de T a T
  • 126. LAMBDAS UnaryOperator<T> ▸ Representa una función de transformación de T a T ▸ Su método funcional es UnaryOperator.apply(Object)
  • 128. LAMBDAS BinaryOperator<T> ▸ Representa una función de Transformación de T, T a T
  • 129. LAMBDAS BinaryOperator<T> ▸ Representa una función de Transformación de T, T a T ▸ Su método funcional es BinaryOperator.apply(Object, Object)
  • 130. METHOD REFERENCES METHOD REFERENCES Consumer<String> consumer = s -> System.out.println(s); Consumer<String> consumer = System.out::println;
  • 131. METHOD REFERENCES METHOD REFERENCES ▸ En algunas ocasiones sólo usamos una Lambda para llamar un método existente
 
 
 
 
 Consumer<String> consumer = s -> System.out.println(s); Consumer<String> consumer = System.out::println;
  • 132. METHOD REFERENCES METHOD REFERENCES ▸ En algunas ocasiones sólo usamos una Lambda para llamar un método existente
 
 
 
 
 ▸ Referencias a Métodos son una forma simple y fácil de leer para implementar expresiones lambda con métodos que ya tienen nombre Consumer<String> consumer = s -> System.out.println(s); Consumer<String> consumer = System.out::println;
  • 133. METHOD REFERENCES TIPOS DE METHOD REFERENCES
  • 134. METHOD REFERENCES TIPOS DE METHOD REFERENCES ▸ Referencia a un método estático - ContainingClass::staticMethodName
  • 135. METHOD REFERENCES TIPOS DE METHOD REFERENCES ▸ Referencia a un método estático - ContainingClass::staticMethodName ▸ Referencia a un método de instancia de un objeto específico - containingObject::instanceMethodName
  • 136. METHOD REFERENCES TIPOS DE METHOD REFERENCES ▸ Referencia a un método estático - ContainingClass::staticMethodName ▸ Referencia a un método de instancia de un objeto específico - containingObject::instanceMethodName ▸ Referencia a un método de instancia de cualquier objeto de un tipo definido - ContainingType::methodName
  • 137. METHOD REFERENCES TIPOS DE METHOD REFERENCES ▸ Referencia a un método estático - ContainingClass::staticMethodName ▸ Referencia a un método de instancia de un objeto específico - containingObject::instanceMethodName ▸ Referencia a un método de instancia de cualquier objeto de un tipo definido - ContainingType::methodName ▸ Referencia a un constructor - ClassName::new
  • 138. EJERCICIOLAMBDAS PRIMER EJERCICIO ▸ Clonar el repositorio:
 
 
 git clone https://github.com/SergioMartinezP/LambdaStream
 
 
 
 ▸ Ejercicio a resolver: EjercicioLambdas.java
  • 140. OPTIONAL Optional ▸ Contenedor de un objeto que puede o no ser null
  • 141. OPTIONAL Optional ▸ Contenedor de un objeto que puede o no ser null ▸ Si contiene un valor, isPresent() regresa true y get() el valor
  • 142. OPTIONAL Optional ▸ Contenedor de un objeto que puede o no ser null ▸ Si contiene un valor, isPresent() regresa true y get() el valor ▸ Es inmutable y tiene métodos para caso como: 
 orElse(T) 
 orElseGet(Supplier<? extends T> other) 
 orElseThrow(Supplier<? extends X> 
 exceptionSupplier)
  • 143. STREAM API CASO DE EJEMPLO: CALCULAR EL PROMEDIO DE EDAD DE LOS ELEGIBLES A BEBER
  • 144. STREAM API CASO DE EJEMPLO: CALCULAR EL PROMEDIO DE EDAD DE LOS ELEGIBLES A BEBER ... List<Person> list ... double ageAverageElegibleDrivers() { double sum = 0; int cont = 0; for (Person p : list) { if (p.getAge()>=21){ sun += p.getAge(); cont++; } } return sum/cont; }
  • 146. STREAM API APLICANDO STREAMS ... List<Person> list ... double ageAverageElegibleDrivers(){ return list.stream() .filter(p -> p.age>21) .mapToInt(p->p.getAge()) .average() .orElse(0.0); }
  • 148. STREAM API STREAM API ▸ Diseñado para trabajar principalmente con colecciones
  • 149. STREAM API STREAM API ▸ Diseñado para trabajar principalmente con colecciones ▸ Provee de una manera "declarativa" de procesar una colección
  • 150. STREAM API STREAM API ▸ Diseñado para trabajar principalmente con colecciones ▸ Provee de una manera "declarativa" de procesar una colección ▸ Se puede ver como un Iterador elegante de una colección
  • 151. STREAM API STREAM API ▸ Diseñado para trabajar principalmente con colecciones ▸ Provee de una manera "declarativa" de procesar una colección ▸ Se puede ver como un Iterador elegante de una colección ▸ Facilita la paralelización del procesamiento de la información
  • 152. STREAM API ¿QUÉ ES UN STREAM?
  • 153. STREAM API ¿QUÉ ES UN STREAM? ▸ Secuencia de elementos
  • 154. STREAM API ¿QUÉ ES UN STREAM? ▸ Secuencia de elementos ▸ No almacena valores, los genera bajo demanda
  • 155. STREAM API ¿QUÉ ES UN STREAM? ▸ Secuencia de elementos ▸ No almacena valores, los genera bajo demanda ▸ Fuente de datos
  • 156. STREAM API ¿QUÉ ES UN STREAM? ▸ Secuencia de elementos ▸ No almacena valores, los genera bajo demanda ▸ Fuente de datos ▸ Consumen desde una fuente de datos como Colecciones, Arreglos e I/O
  • 157. STREAM API ¿QUÉ ES UN STREAM? (2)
  • 158. STREAM API ¿QUÉ ES UN STREAM? (2) ▸ Operaciones de Agregación
  • 159. STREAM API ¿QUÉ ES UN STREAM? (2) ▸ Operaciones de Agregación ▸ Operaciones estilo base de datos como: filter, map, reduce, findFirst, allMatch, sorted, …
  • 160. STREAM API ¿QUÉ ES UN STREAM? (2) ▸ Operaciones de Agregación ▸ Operaciones estilo base de datos como: filter, map, reduce, findFirst, allMatch, sorted, … ▸ Encadenamiento
  • 161. STREAM API ¿QUÉ ES UN STREAM? (2) ▸ Operaciones de Agregación ▸ Operaciones estilo base de datos como: filter, map, reduce, findFirst, allMatch, sorted, … ▸ Encadenamiento ▸ La mayoría de las operaciones regresan un stream, por lo que se pueden encadenar. El procesamiento se hace sólo al alcanzar una operación terminal
  • 162. STREAM API ¿QUÉ ES UN STREAM? (3)
  • 163. STREAM API ¿QUÉ ES UN STREAM? (3) ▸ Iteración Interna
  • 164. STREAM API ¿QUÉ ES UN STREAM? (3) ▸ Iteración Interna ▸ La iteración es decidida internamente y reflejará la forma en que se encadenaron las operaciones
  • 165. STREAM API STREM VS COLLECTION
  • 166. STREAM API STREM VS COLLECTION ▸ Sin Almacenamiento
  • 167. STREAM API STREM VS COLLECTION ▸ Sin Almacenamiento ▸ Funcionales
  • 168. STREAM API STREM VS COLLECTION ▸ Sin Almacenamiento ▸ Funcionales ▸ Flojas
  • 169. STREAM API STREM VS COLLECTION ▸ Sin Almacenamiento ▸ Funcionales ▸ Flojas ▸ Posiblemente Ilimitadas
  • 170. STREAM API STREM VS COLLECTION ▸ Sin Almacenamiento ▸ Funcionales ▸ Flojas ▸ Posiblemente Ilimitadas ▸ limit(n) findFirst()
  • 171. STREAM API STREM VS COLLECTION ▸ Sin Almacenamiento ▸ Funcionales ▸ Flojas ▸ Posiblemente Ilimitadas ▸ limit(n) findFirst() ▸ Consumibles
  • 174. STREAM API PIPELINE ▸ Fuente de datos ▸ una o varias operaciones Intermedias
  • 175. STREAM API PIPELINE ▸ Fuente de datos ▸ una o varias operaciones Intermedias ▸ Son operaciones que regresan otro stream, por lo que se pueden encadenar, no se ejecutan sino hasta que el stream tenga una operación terminal y deberían utilizar funciones sin efectos colaterales
  • 176. STREAM API PIPELINE ▸ Fuente de datos ▸ una o varias operaciones Intermedias ▸ Son operaciones que regresan otro stream, por lo que se pueden encadenar, no se ejecutan sino hasta que el stream tenga una operación terminal y deberían utilizar funciones sin efectos colaterales ▸ una operación Terminal
  • 177. STREAM API PIPELINE ▸ Fuente de datos ▸ una o varias operaciones Intermedias ▸ Son operaciones que regresan otro stream, por lo que se pueden encadenar, no se ejecutan sino hasta que el stream tenga una operación terminal y deberían utilizar funciones sin efectos colaterales ▸ una operación Terminal ▸ Son operaciones que "Terminan" un stream, usualmente tienen efectos colaterales e inician el procesamiento del stream y producen un resultado
  • 178. STREAM API ¿DE DÓNDE OBTENEMOS LOS STREAMS? (FUENTES) ▸ De una Colección usando los métodos stream() y parallelStream() ▸ De un arreglo Arrays.stream(Object[]) ▸ De las clases stream Stream.of(Object[]), IntStream.range(int, int) ▸ De un archivo BufferedReader.lines() ▸ De directorios, patrones, números aleatorios y/o creadas por nosotros
  • 180. STREAM API APLICANDO STREAMS ... List<Person> list ... double ageAverageElegibleDrivers(){ return list.stream() .filter(p -> p.age>21) .mapToInt(p->p.getAge()) .average() .orElse(0.0); }
  • 181. STREAM API APLICANDO STREAMS ... List<Person> list ... double ageAverageElegibleDrivers(){ return list.stream() .filter(p -> p.age>21) .mapToInt(p->p.getAge()) .average() .orElse(0.0); } fuente intermedias terminal
  • 182. STREAM API LOS STREAMS SON OBJETOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .map(s -> s.getScore()) .max();
  • 183. STREAM API LOS STREAMS SON OBJETOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .map(s -> s.getScore()) .max(); regresa un int
  • 184. STREAM API LOS STREAMS SON OBJETOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .map(s -> s.getScore()) .max(); regresa un int map debe envolver el int 
 en un Integer
  • 185. STREAM API LOS STREAMS SON OBJETOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .map(s -> s.getScore()) .max(); regresa un int map debe envolver el int 
 en un Integer max extrae cada Integer
 para obtener el mayor
  • 186. STREAM API STREAMS DE PRIMITIVOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .mapToInt(s -> s.getScore()) .max();
  • 187. STREAM API STREAMS DE PRIMITIVOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .mapToInt(s -> s.getScore()) .max(); mapToInt produce un stream de int, 
 así ya no hay boxing o unboxing
  • 188. STREAM API STREAMS DE PRIMITIVOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .mapToInt(s -> s.getScore()) .max(); mapToInt produce un stream de int, 
 así ya no hay boxing o unboxing ▸ Para mejorar la eficiencia existen tres tipos de stream primitivos
  • 189. STREAM API STREAMS DE PRIMITIVOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .mapToInt(s -> s.getScore()) .max(); mapToInt produce un stream de int, 
 así ya no hay boxing o unboxing ▸ Para mejorar la eficiencia existen tres tipos de stream primitivos ▸ IntStream, DoubleStream y LongStream
  • 190. STREAM API STREAMS DE PRIMITIVOS int highScore = students.stream() .filter(s -> s.gradutationYear() == 2015) .mapToInt(s -> s.getScore()) .max(); mapToInt produce un stream de int, 
 así ya no hay boxing o unboxing ▸ Para mejorar la eficiencia existen tres tipos de stream primitivos ▸ IntStream, DoubleStream y LongStream ▸ Usar metodos como mapToInt(), mapToDouble() y mapToLong()
  • 191. STREAM API OPERACIONES INTERMEDIAS - FUENTES ▸ generate(Supplier<T> s) ▸ Genera una secuencia infinita y desordenada de los valores producidos por Supplier ▸ of(T t) of(T... values) ▸ Genera un stream con un solo elemento T o una secuencia de valores T ▸ iterate(T seed, UnaryOperator<T> f) ▸ Genera una secuencia infinita producida de aplicar iterativamente la función f(seed), f(f(seed)),…
  • 192. STREAM API OPERACIONES INTERMEDIAS - FILTRADO ▸ filter(Predicate<? super T> predicate) ▸ Regresa un stream que contiene sólo los elementos que corresponden tras aplicar el Predicate proporcionado ▸ limit(long maxSize) ▸ Regresa un stream truncado con a lo mucho maxSize elementos ▸ skip(long n) ▸ Regresa un stream con los elementos sobrantes tras descartar los primeros n elementos
  • 193. STREAM API OPERACIONES INTERMEDIAS - ORDEN ▸ distinct() ▸ Regresa un stream que contiene sólo los elementos que son diferentes aplicando un Object.equals(Object) ▸ sorted() ▸ Regresa un stream ordenado según el orden natural de los objetos contenidos ▸ sorted(Comparator<? super T> comparator) ▸ Regresa un stream ordenado según el Comparator proporcionado
  • 194. STREAM API OPERACIONES INTERMEDIAS - MAPEO ▸ map(Function<? super T,? extends R> mapper) ▸ Regresa un stream que contiene los resultados de aplicar la función proporcionada a cada elemento ▸ flatMap(Function<? super T,? extends Stream<? extends R>> mapper) ▸ Regresa un stream que reemplaza los elementos del stream actual por los elementos del stream mapeado ▸ orders.flatMap(order -> order.getLineItems().stream())
  • 195. STREAM API OPERACIONES INTERMEDIAS - MAPEO Map FlatMap
  • 196. STREAM API OPERACIONES TERMINALES - MATCH ▸ allMatch(Predicate<? super T> predicate) ▸ true si todos los elementos pasan la prueba del Predicate ▸ anyMatch(Predicate<? super T> predicate) ▸ true si alguno de los elementos pasa la prueba del Predicate ▸ noneMatch(Predicate<? super T> predicate) ▸ true si ninguno de los elementos pasa la prueba del Predicate
  • 197. STREAM API OPERACIONES TERMINALES - NUMÉRICOS ▸ max(Comparator<? super T> comparator) ▸ Optional del elemento mayor según comparator ▸ min(Comparator<? super T> comparator) ▸ Optional del elemento menor según comparator ▸ count() ▸ Cantidad de elementos en el stream
  • 198. STREAM API OPERACIONES TERMINALES - MÁS NUMÉRICOS ▸ Para los Streams de Primitivos IntStream, LongStream, DoubleStream ▸ average() ▸ Obtiene el promedio de los elementos ▸ Regresa un Optional pues la lista puede estar vacía ▸ sum() ▸ Obtiene la suma de los elementos
  • 199. STREAM API OPERACIONES TERMINALES - REDUCTORES ▸ reduce(BinaryOperator<T> accumulator) ▸ Reducción de elementos de este stream usando una función de acumulación asociativa ▸ Este acumulador toma un resultado parcial y el siguiente elemento y regresa un resultado parcial ▸ Regresa un Optional
  • 200. STREAM API REDUCTORES ▸ Encontrar la longitud de la línea mas larga de un archivo Path input = Paths.get("lines.txt"); int longestLineLength = Files.lines(input) .mapToInt(String::length) .max() .getAsInt();
  • 201. STREAM API REDUCTORES ▸ Encontrar la longitud de la línea mas larga de un archivo
  • 202. STREAM API REDUCTORES ▸ Encontrar la longitud de la línea mas larga de un archivo String longest = Files.lines(input) .sort((x, y) -> y.length() - x.length()) .findFirst() .get();
  • 203. STREAM API REDUCTORES ▸ Encontrar la longitud de la línea mas larga de un archivo String longest = Files.lines(input) .sort((x, y) -> y.length() - x.length()) .findFirst() .get(); ¿Y si el archivo es muy grande?
  • 204. STREAM API REDUCTORES - ALTERNATIVAS ▸ Usar un while y una variable que contenga el resultado ▸ simple, pero no es thread safe ▸ Usar recursión ▸ No tiene una variable mutable, por lo que es thread safe ▸ En un archivo largo podemos tener un stack overflow ▸ Usar reduce(BinaryOperator<T> accumulator) ▸ El accumulator obtiene un resultado parcial y el siguiente elemento ▸ Como con recursión, pero sin el stack overflow
  • 205. STREAM API REDUCTORES ▸ Encontrar la línea mas larga de un archivo String longestLine = Files.lines(input) .reduce((x, y) -> { if (x.length() > y.length()) return x; return y; }) .get();
  • 206. STREAM API REDUCTORES ▸ Encontrar la línea mas larga de un archivo String longestLine = Files.lines(input) .reduce((x, y) -> { if (x.length() > y.length()) return x; return y; }) .get(); La x mantiene el estado, 
 en este caso guarda la linea más larga
  • 207. STREAM API OPERACIONES TERMINALES - COLECTORES ▸ collect(Collector<? super T,A,R> collector) ▸ Realiza una reducción mutable de los elementos del stream ▸ El Contenedor del resultado puede ser un List, Map, String, etc ▸ toArray() ▸ Regresa un Array con los elementos del Stream
  • 208. STREAM API COLLECTORS ▸ La clase Collectors implementa muchos colectores como: ▸ toList() ▸ List<String> list = people.stream()
 .map(Person::getName)
 .collect(Collectors.toList()); ▸ toCollection(Supplier<C> collectionFactory) ▸ Set<String> set = people.stream()
 .map(Person::getName).collect(
 Collectors.toCollection(TreeSet::new));
  • 209. STREAM API COLLECTORS - A UN MAPA ▸ toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) ▸ Map<String, Student> studentIdToStudent 
 students.stream()
 .collect(toMap(Student::getId,
 Functions.identity()); ▸ toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) ▸ Map<String, String> phoneBook = 
 people.stream().collect(toMap(Person::getName, 
 Person::getAddress, (s, a) -> s + ", " + a)); ▸ Para mapas concurrentes usar toConcurrentMap(…)
  • 210. STREAM API COLLECTORS - AGRUPACIONES ▸ groupingBy(Function<? super T,? extends K> classifier) ▸ Map<Department, List<Employee>> byDept = employees.stream().collect(
 Collectors.groupingBy(Employee::getDepartment)); ▸ groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) ▸ Map<City, Set<String>> namesByCity = people.stream().collect(groupingBy(
 Person::getCity, mapping(Person::getLastName, toSet()))); ▸ Para agrupaciones concurrentes usar groupingByConcurrent(…)
  • 211. STREAM API COLLECTORS - UNIENDO CADENAS ▸ Otra forma de coleccionar resultados es concatenarlos en cadenas ▸ joining() ▸ joining(CharSequence delimiter) ▸ joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) String joined = things.stream()
 .map(Object::toString)
 .collect(Collectors.joining(", "));
  • 212. STREAM API OPERACIONES TERMINALES - ITERACIÓN ▸ Stream cuenta con métodos para iterar el stream resultante, pero dependiendo de lo que se esté haciendo muy probablemente alguno de los colectores anteriores lo pueda realizar ▸ forEach(Consumer<? super T> action) ▸ Realiza la action para cada elemento en el stream ▸ forEachOrdered(Consumer<? super T> action) ▸ Realiza la action para cada elemento en el stream garantizando el orden si se ejecuta en paralelo
  • 213. EJERCICIOSTREAMS ▸ En el mismo repositorio: ▸ EjercicioStreams.java ▸ En el ejercicio 6 se requiere también completar: ▸ RandomWords.java
  • 214. STREAM API PROCESAMIENTO EN PARALELO ▸ Una "ventaja" del uso de streams es su facilidad para convertirlas a procesos paralelos ▸ Para convertir un stream a procesamiento en paralelo sólo hay que agregar parallel() al pipeline o usar parallelStream() al generar el stream ▸ Basado en el framework Fork-Join ▸ Considerarlo si, y sólo si, las operaciones intermedias o terminales a realizar son computacionalmente pesadas y se tienen miles de elementos
  • 215. GRACIAS EN RESUMEN ▸ En Java 8 contamos con nuevas herramientas ▸ Lambdas - Funciones independientes para realizar tareas muy específicas ▸ Optional - Forma de manejar la incertidumbre ▸ Streams - Forma de procesar colecciones o secuencias de valores