lambdas y api stream #perújug #java20

48
Perú JUG DIC-2015 Alexis López @aa_lopez

Upload: alexis-lopez

Post on 09-Apr-2017

274 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Lambdas y API Stream #PerúJUG #Java20

Perú JUGDIC-2015

Alexis López@aa_lopez

Page 2: Lambdas y API Stream #PerúJUG #Java20

Agenda

Expresiones Lambda

Stream API

Taller Práctico

11

22

33

Page 3: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaFunciones como valores/parámetros

<<interface>>ApplePredicate

+test(Apple):boolean

AppleGreenColorPredicate AppleRedColorPredicate

AppleHeavyWeightPredicateAppleRedAndHeavyPredicate

+test(Apple):boolean +test(Apple):boolean

+test(Apple):boolean +test(Apple):boolean

Apple

+getWeight():double+getColor():String

Page 4: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaFunciones como valores/parámetros

public class AppleHeavyWeightPredicate implements ApplePredicate{public boolean test(Apple apple){

return apple.getWeight() > 150;}

}

public class AppleGreenColorPredicate implements ApplePredicate{public boolean test(Apple apple){

return "green".equals(apple.getColor());}

}

...

Código tomado del libro Java 8 in Action

Page 5: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaFunciones como valores/parámetros

public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p){List<Apple> result = new ArrayList<>();for(Apple apple: inventory){

if(p.test(apple)){result.add(apple);

}}return result;

}

...

Código tomado del libro Java 8 in Action

Nuestro predicado encapsulala condición

Page 6: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaFunciones como valores/parámetros

List<Apple> inventory = ...//Separar manzanas por colorList<Apple> greenApples = filterApples(inventory, new

AppleGreenColorPredicate());

//Separar manzanas por pesoList<Apple> heavyApples = filterApples(inventory, new

AppleHeavyWeightPredicate());

...

Código tomado del libro Java 8 in Action

public boolean test(Apple apple){return apple.getWeight() > 150;

}

Necesitaríamos muchas clases...

Page 7: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaFunciones como valores/parámetros

…List<Apple> inventory = ...List<Apple> redApples = filterApples(inventory, new ApplePredicate() {

public boolean test(Apple apple){ return "red".equals(apple.getColor());}

});

List<Apple> greenApples = filterApples(inventory, new ApplePredicate() {

public boolean test(Apple apple){return "green".equals(apple.getColor());

}});

...

Código tomado del libro Java 8 in Action

Enredado, repetido...

Page 8: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaFunciones como valores/parámetros

...List<Apple> inventory = …

List<Apple> redApples = filterApples(inventory, (Apple a) -> "red".equals(a.getColor());

List<Apple> greenApples = filterApples(inventory, (Apple a) -> "green".equals(a.getColor()));

...

Código tomado del libro Java 8 in Action

Parametrización de comportamiento

Page 9: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefinición

Métodos anónimos, es decir, métodos sin nombre o clase.

Paquete java.util.function

Permite escribir código más claro que usar clases anónimas.

(parámetros) -> {cuerpo expresión lambda}

Operador lambda

Page 10: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefinición

Ejemplos de expresiones lambda:(int a, int b) -> a + ba -> a + 1(int a, int b) -> { System.out.println(a + b); return a + b; }

• El cuerpo puede lanzar excepciones• Una sola línea no requiere llaves ni la sentencia return• Varias líneas requieren separador punto y coma (;)• Un solo parámetro no requiere paréntesis• Ningún parámetro requiere paréntesis vacíos

Parámetros CuerpoOperador lambda

Page 11: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Interfaces Recargadas - Métodos por Defecto

Definidos e implementados en la Interface.

Implementación por defecto se usa solo cuando la clase implementadora no provee su propia implementación

Para quien invoca, es un método más de la Interface.

Especial cuidado cuando se implementen Interfaces con métodos por defecto iguales…

public interface MorningInterface { default void saludo(){ System.out.println("Buenos días"); }}

public interface AfternoonInterface { default void saludo(){ System.out.println("Buenas tardes"); }}

Interface List<T> {…

default void sort(Comparator<? super T> cmp){

Collections.sort(this, cmp); }

…}

Page 12: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Interfaces Recargadas - Métodos por Defecto

En caso de conflictos, este es el orden en el que se selecciona el método por defecto:

1. Implementaciones en clases concretas2. Implementaciones en subinterfaces3. Explícitamente seleccionando el método usando: X.super.m(...)

Donde X es la interface y m es el método deseado

También debemos notar que, a partir de Java 8, además de métodos por defecto, las interfaces también pueden proveer implementación de métodos estáticos.

Page 13: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Interfaces Recargadas - Métodos por Defecto

public class MultipleInheritance implements MorningInterface{ public static void main(String... args) { MultipleInheritance m = new MultipleInheritance();

m.saludo(); //Buenos días }}

Page 14: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Interfaces Recargadas - Métodos por Defecto

public class MultipleInheritance implements MorningInterface, AfternoonInterface { public static void main(String... args) { MultipleInheritance m = new MultipleInheritance();

m.saludo(); //Saludo desde clase implementadora m.saludoMañanero(); //Buenos días m.saludoTarde(); //Buenas tardes }

@Override public void saludo() { System.out.println("Saludo desde clase implementadora"); }

public void saludoMañanero() { MorningInterface.super.saludo(); }

public void saludoTarde() { AfternoonInterface.super.saludo(); }}

En este caso es obligatorio implementar el método

En este caso es obligatorio implementar el método

Page 15: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Interfaces Funcionales

SAM: Single Abstract Method.

Interface Funcional: Interface con un solo método abstracto (SAM) y diferente a los métodos de Object (toString, equals…).

@FunctionalInterfaceIndica al compilador que debe verificar si se trata de una interfase funcional.

@FunctionalInterfacepublic interface InterfaceEjemplo{ /** Imprime algo*/ void imprimir(); /** Método de Object, no cuenta contra SAM*/ boolean equals(Object obj);}

//Ejemplo de Interfases funcionales que ya conocemos:

Interface Runnable { void run(); }

Interface Comparator<T> { boolean compare(T x, T y);

}

Interface ActionListener { void actionPerformed(…); }

Page 16: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Interface Funcional – 4 Grandes Grupos

@FunctionalInterfacepublic interface Supplier<T> {

T get();

//Otros métodos...}

@FunctionalInterfacepublic interface Function<T, R> {

R apply(T);

//Otros métodos...}

@FunctionalInterfacepublic interface Predicate<T> {

boolean test(T t);

//Otros métodos...}

@FunctionalInterfacepublic interface Consumer<T> {

void accept(T t);

//Otros métodos...}

Uso: Mapear de un valor a otro

Uso: Creación de objetosUso: Validación de criterios

Uso: Consumir métodos del parámetro. Tiene efectos secundarios

Page 17: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Inferencia de tipos

//Comparator usando clases anónimas...

Comparator<String> c = new Comparator<String>() {public int compare(String x, String y) {

return x.length() - y.length();}

};

//Comparator usando Lambdas...

Comparator<String> c = (x, y) -> x.length() - y.length();

Contexto de asignaciónContexto de asignación

Page 18: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Inferencia de tipos

//Comparator usando clases anónimas...

Comparator<String> c = new Comparator<String>() {public int compare(String x, String y) {

return x.length() - y.length();}

};

//Comparator usando Lambdas...

Comparator<String> c = (x, y) -> x.length() - y.length();

Contexto de asignaciónContexto de asignación

Page 19: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Inferencia de tipos - Casos especiales

//Misma expresión lambda, diferentes interfaces funcionalesCallable<Integer> c = () -> 42;PrivilegedAction<Integer> p = () -> 42;

//void-compatibility ruleList<String> list = ...Predicate<String> p = s -> list.add(s);Consumer<String> c = s -> list.add(s);

Aunque el método abstracto de Consumerretorna void, no hay error de compilación

Page 20: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Alcance

Efectivamente Constante: Variable o parámetro que solo es asignado una vez.

this hace referencia a la instancia de la clase sobre la cual se ha escrito la expresión Lambda.

void expire(File root, long before) {...root.listFiles(File p -> p.lastModified() <= before);...

//Esto causaría error de compilaciónbefore = 10000;}

class SessionManager {long before = ...;void expire(File root) {...

root.listFiles(File p -> checkExpiry(p.lastModified(), this.before));

}boolean checkExpiry(long time, long expiry) { ... }}

Page 21: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Métodos de Referencia

Invocación de métodos por su nombre. Expresiones Lambda más compactas y fáciles de leer.

Solo para cuando la expresión lambda tiene una sola sentencia.

Existen 4 tipos:Métodos EstáticosMétodos de Instancia de un objetoMétodos de Instancia de algún tipoConstructores

//Uso para métodos estáticosClase::metodoEstatico//Uso para métodos de instancia de un objeto existenteObjeto::metodoDeInstancia//Uso para métodos de instancia de algún tipo de objetoTipo::metodoDeInstancia//Uso para constructoresClase::new

public class Person {

String name; LocalDate birthday; //gets…sets…

public static int compareByAge(Person a, Person b) { return a.birthday.compareTo(b.birthday); }}

Page 22: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Métodos de Referencia::Métodos Estáticos

public class Testing{

public static void main(String… args){

Person[] personArray = new Person[1000];…//ingresar objetos tipo persona al arreglo...…//Ordenar el arreglo usando lambdasArrays.sort(personArray, (a, b) -> Person.compareByAge(a, b));

//Ordenar el arreglo usando métodos de referenciaArrays.sort(personArray, Person::compareByAge);

}}

Page 23: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Métodos de Referencia::Métodos de Instancia de un objeto

public class ComparisonProvider { public int compareByName(Person a, Person b) { return a.getName().compareTo(b.getName());}}...public class Testing{

public static void main(String… args){

Person[] personArray = new Person[1000];//ingresar objetos tipo persona al arreglo...

ComparisonProvider myComparisonProvider = new ComparisonProvider();//Ordenar el arreglo usando lambdasArrays.sort(personArray, (a,b)->myComparisonProvider.compareByName(a, b));

//Ordenar el arreglo usando métodos de referenciaArrays.sort(personArray, myComparisonProvider::compareByName);

}}

Page 24: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Métodos de Referencia::Métodos de Instancia de algún Tipo

public class Testing{

public static void main(String… args){

String[] stringArray = {"Zuñiga", "James", "Cuadrado", "John", "Armero", "Murillo", "Falcao", "Martínez"};

//Ordenar el arreglo usando lambdasArrays.sort(stringArray, (a, b) -> a.compareToIgnoreCase(b));

//Ordenar el arreglo usando métodos de referenciaArrays.sort(stringArray, String::compareToIgnoreCase);

}}

Page 25: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Métodos de Referencia::Constructores

public class Testing{

public static void main(String… args){

//Crear una persona usando lambdasSupplier<Persona> s1 = () -> new Persona();

Persona p1 = s1.get();

//Crear una persona usando métodos de referenciaSupplier<Persona> s1 = Persona::new;Persona p1 = s1.get();

}}

Page 26: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Métodos de Referencia::Constructores

public class Manzana{private int peso;public Manzana(int w){ peso = w;}

}…

//Crear una manzana usando lambdasFunction<Integer, Manzana> f1 = (w) -> new Manzana(w);Manzana m1 = f1.apply(100);

//Crear una manzana usando métodos de referenciaFunction<Integer, Manzana> f1 = Manzana::new;Manzana m1 = f1.apply(100);

...

Page 27: Lambdas y API Stream #PerúJUG #Java20

Expresiones LambdaDefiniciones – Expresiones Compuestas

Usar métodos por defecto para crear expresiones más complejas.

Predicate<T>Incluye métodos and, or, negate.

Function<T,R>Incluye métodos andThen y compose.

Comparator<T>Incluye métodos reversed, comparing, thenComparing.

//Creación de predicados complejosPredicate<String> p1 = s -> s.length() > 3;Predicate<String> p2 = s -> s.charAt(0) == 'A';Predicate<String> p3 = ...

//Precedencia de izquierda a derechaPredicate<String> p4 = p1.or(p2).and(p3).negate();

//Composición de funcionesFunction<String, Integer> f1 = String::length;Function<Integer, Integer> f2 = i -> i * 2;

//Primero aplica f1 y al resultado aplica f2Function<String, Integer> f3 = f1.andThen(f2);

//Composición de comparadoresComparator<String> c1 = (a,b) -> a.length() - b.length();Comparator<String> c2 = String::compareTo;

//Primero compare con c1 y si son iguales use c2Comparator<String> c3 = c1.thenComparing(c2);

Page 28: Lambdas y API Stream #PerúJUG #Java20

Stream APIDefiniciones - Stream

Secuencia de elementos de una fuente que soporta operaciones para el procesamiento de sus datos:

1. De forma declarativa usando expresiones lambda.2. Es posible el encadenamiento de varias operaciones haciendo al

código fácil de leer y con un objetivo claro.3. Operaciones se ejecutan de forma secuencial o paralela (Fork/Join)

Paquete java.util.stream

Interfase java.util.stream.Stream

Map

Reduce

Filter

Page 29: Lambdas y API Stream #PerúJUG #Java20

Stream APIDefiniciones - Stream

Un Stream está compuesto de tres (3) partes:

1. Una fuente de información2. Cero o más operaciones intermedias3. Una operación final: Produce un resultado o un efecto en los datos

List transacciones = ...int sum = transacciones.stream().

filter(t -> t.getProveedor().getCiudad().equals(“Cali”)). mapToInt(Transaccion::getPrecio). sum();

Fuente

Operaciones intermediasOperación terminal

Page 30: Lambdas y API Stream #PerúJUG #Java20

Stream APIDefiniciones - Stream

Propiedades de un Stream:

1. Operaciones intermedias retornan otro Stream = Encadenamiento de operaciones

2. Operaciones intermedias son encoladas hasta que una operación terminal sea invocada

3. Solo puede ser recorrido una vez (IllegalStateException)

4. Iteración interna = Iteración automática● Iteración secuencial o paralela transparante para el desarrollador ● Permite definir el “Qué quiero lograr” en vez del “Cómo lo quiero lograr”

5. Versiones “primitivas” evitan el Autoboxing y Unboxing ● DoubleStream● IntStream● LongStream

Page 31: Lambdas y API Stream #PerúJUG #Java20

Stream APIDefiniciones – Stream - Creación

Diferentes formas de obtener un Stream

1. Stream.of(T): Stream<T> -> Retorna un Stream ordenado y secuencial de los elementos pasados por parámetro

2. Stream.empty():Stream -> Retorna un Stream secuencial vacío.

3. Arrays.stream(T[]):Stream<T> -> Retorna un Stream secuencial del arreglo pasado por parámetro. Versión “primitiva” retorna: DoubleSTream, IntStream, LongStream.

4. Collection<E>.stream():Stream<E> -> Retorna un Stream secuencial de los elementos de la colección. Versión en paralelo: Collection<E>.parallelStream():Stream<E>

5. Stream.iterate(T, UnaryOperator<T>):Stream<T> -> Retorna un Stream infinito, ordenado y secuencial, a partir del valor inicial T y de aplicar la función UnaryOperator al valor inicial para obtener los demás elementos. Para limitar su tamaño, se puede usar el método +limit(long):Stream

6. Stream.generate(Supplier<T>):Stream<T> -> Retorna un Stream infinito, scuencial pero no ordenado, a partir de una expresión lambda que provee los elementos.

Page 32: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos - Filter

Para filtrar los elementos de un Stream podemos usar los siguientes métodos:

+filter(Predicate<T>):Stream<T> -> Retorna un Stream que contiene solo los elementos que cumplen con el predicado pasado por parámetro.

+distinct():Stream<T> -> Retorna un Stream sin elementos duplicados. Depende de la implementación de +equals(Object):boolean.

+limit(long):Stream<T> -> Retorna un Stream cuyo tamaño no es mayor al número pasado por parámetro. Los elementos son cortados hasta ese tamaño.

+skip(long):Stream<T> -> Retorna un Stream que descarta los primeros N elementos, donde N es el número pasado por parámetro. Si el Stream contiene menos elementos que N, entonces retorna un Stream vacío.

Map

Reduce

Filter

Page 33: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos - Map

Podemos transformar los elementos de un Stream al extraer información de éstos. Para lograrlo podemos usar alguno de los siguientes métodos:

+map(Function<T, R>): Stream<R> -> Retorna un Stream que contiene el resultado de aplicar la función pasada por parámetro a todos los elementos del Stream. Transforma los elementos de T a R.

También existe en su versión “primitiva”:+mapToDouble(ToDoubleFunction<T>): DoubleStream+mapToInt(ToIntFunction<T>): IntStream+mapToLong(ToLongFunction<T>): LongStream

La ventaja de usar las versiones primitivas radica en que se evita el uso de Autoboxing y Unboxing, lo que en algunas situaciones puede ser deseado por temas de rendimiento.

Map

Reduce

Filter

Page 34: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos - Map

+flatMap(Function<T, Stream<R>):Stream<R>Permite transformar cada elemento en un Stream y al final concatenarlos en un solo Stream.

También existe en su versión “primitiva”:+flatMapToDouble(Function<T, DoubleStream): DoubleStream+flatMapToInt(Function<T, IntStream): IntStream+flatMapToLong(Function<T, LongStream): LongStream

La ventaja de usar las versiones primitivas radica en que se evita el uso de Autoboxing y Unboxing, lo que en algunas situaciones puede ser deseado por temas de rendimiento.

Map

Reduce

Filter

Page 35: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos - Map

Taller Lambdas y Stream APITaller

Lambdas y Stream APITallerTaller

Lambdas y Stream APITallerTaller

2

Stream<String>

map(s->s.split(“ “))

Stream<String[]>

distinct()

Stream<String[]>

count()ERROR!

Page 36: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos - Map

Taller Lambdas y Stream APITaller

Lambdas y Stream APITallerTaller

5

Stream<String>

map(s->s.split(“ “))

Stream<String[]>

distinct()

Stream<Stream<String>>

count()

flatMap(Arrays::stream)

Lambdas y Stream APITallerTaller

Lambdas y Stream APITaller

CORRECTO!

Stream<String>

Page 37: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos - Reduce

Operaciones terminales provocan que todas las operaciones intermedias sean ejecutadas.

Existen operaciones terminales que permiten obtener datos del Stream como: conteo, mínimo, máximo, búsqueda, y en general reducir el Stream a un valor.

Existen algunas operaciones terminales cuyo propósito es el consumo de los elementos del Stream, por ejemplo: +foreach(Consumer<T>):void

Existen otras operaciones terminales que permiten recolectar los elementos de un Stream en estructuras mutables.

Map

Reduce

Filter

Page 38: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos – Reduce - Agregación

Entre las operaciones terminales que permiten obtener datos del Stream tenemos:

+count():long -> Retorna la cantidad de elementos en el Stream

+max(Comparator<T>):Optional<T> -> Retorna el elemento máximo del Stream basado en el comparador pasado por parámetro. Nótese que el retorno es de tipo Optional.

+min(Comparator<T>):Optional<T> -> Retorna el elemento mínimo del Stream basado en el comparador pasado por parámetro. Nótese que el retorno es de tipo Optional.

Map

Reduce

Filter

Page 39: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos – Reduce - Búsqueda

+allMatch(Predicate<T>):boolean -> Verifica si todos los elementos del Stream satisfacen el predicado pasado por parámetro. Si alguno no lo cumple, para la verificación y retorna falso.

+anyMatch(Predicate<T>):boolean -> Verifica si alguno de los elementos del Stream satisface el predicado pasado por parámetro. Si alguno lo cumple, para la verificación y retorna verdadero.

+noneMatch(Predicate<T>):boolean -> Verifica si todos los elementos del Stream NO satisfacen el predicado pasado por parámetro. Si alguno SI lo cumple, para la verificación y retorna false.

+findAny():Optional<T> -> Retorna algún elemento del Stream. Nótese el retorno es de tipo Optional.

+findFirst():Optional<T>: Retorna el primer elemento del Stream. Nótese el retorno es de tipo Optional.

Map

Reduce

Filter

Page 40: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos – Reduce

+reduce(BinaryOperator<T>):Optional<T>Realiza la reducción del Stream usando una función asociativa.

+reduce(T, BinaryOperator<T>):TRealiza la reducción del Stream usando un valor inicial y una función asociativa.

List<Integer> numeros = …

//Obtiene el posible número mayor par del StreamOptional<Integer> opt = numeros

.stream() .filter(x -> x % 2 == 0) .reduce(Integer::max);

//Obtiene la suma de los elementos del StreamInteger suma = numeros

.stream() .reduce(0, (x,y) -> x + y);

Page 41: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos – Reduce - Collectors

collect es una operación terminal que permite recolectar los elementos de un Stream.

Collectors es una clase utilitaria que provee métodos estáticos que retornan los recolectores más usados. Dichos recolectores pueden ser agrupados en 3 tipos:

● Reducción y resúmen: Reducen el Stream y permite obtener valores agregados.

● Agrupamiento: Agrupa elementos en un Map usando una función de clasificación.

● Particionamiento: Agrupamiento donde la función de clasificación es un predicado. Agrupa los elementos en un Map de 2 llaves: false y true

Import static java.util.stream.Collectors.*;...List<Integer> numeros = …

//Reducción y resúmen: Cuentalong cuenta = numeros.stream().collect(counting());

//Reducción y resúmen: Sumaint suma = numeros

.stream() .collect(summingInt(x -> x.intValue()));

//Reducción y resúmen: Objeto resúmenIntSummaryStatistics res = numeros

.stream()

.collect(summarizingInt(Integer::intValue));

//Reducción y resúmen: Unión de cadenasString csv = numeros.stream().map(Object::toString)

.collect(joining(", "));

summarizingLongsummarizingDouble

summingLongsummingDouble

Page 42: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos – Reduce - Collectors

Import static java.util.stream.Collectors.*;…List<Empleado> empleados = …

// AgrupamientoMap<String, List<Empleado>> porDept = empleados

.stream() .collect(groupingBy(Empleado::getDepartmento));

Map<String, Long> deptCant = empleados .stream()

.collect(groupingBy(Empleado::getDepartmento), counting());

Map<String, Map<String, List<Empleado>>> dptoCiu = null;dptoCiu = empleados

.stream() .collect(groupingBy(Empleado::getDepartamento, groupingBy(Empleado::getCiudad)));

Función de clasificación

En el Map quedan solo las llavesque tengan valores

Segundo collector permiteagrupar n-niveles

Segundo collector permiteContar la cantidad de elementos

Page 43: Lambdas y API Stream #PerúJUG #Java20

Stream APIOperaciones sobre colecciones de datos – Reduce - Collectors

Import static java.util.stream.Collectors.*;…List<Estudiante> estudiantes = …

//Estudiantes separados entre los que ganaron y perdieron el cursoMap<Boolean, List<Estudiante>> valoracion = estudiantes

.stream() .collect(partitioningBy(s -> s.getNota() >= 3.0));

//Cantidad de estudiantes separados entre los que ganaron y perdieron el cursoMap<Boolean, Long> valoracion = estudiantes

.stream() .collect(partitioningBy(s -> s.getNota() >= 3.0, counting()));

Función de clasificación

Segundo collector permitecontar la cantidad de elementos

particionar n-niveles, etc.

Page 44: Lambdas y API Stream #PerúJUG #Java20

Stream APIDebug

+peek(Consumer<T>):Stream<T>● Operación Intermedia● Cada elemento es pasado al Consumer● No modificar los elementos del Stream

Cuando se requiera definir breakpoints● Usar métodos de referencia● Usar peek entre operaciones intermedias

List<String> palabras = ...List<String> unicas = palabras.stream() .flatMap(w -> Stream.of(w.split(“ “)))

.peek(s -> s.toString()) .map(String::toLowerCase)

.peek(s -> metodoReferencia(s)) .distinct() .collect(Collectors.toList());

Page 45: Lambdas y API Stream #PerúJUG #Java20

Stream APIStreams Paralelos

Propiedades de un Stream Paralelo:

1. Usa Fork/Join internamente

2. Usar +parallel():Stream para convertir a paralelo.

3. Usar +sequential():Stream para convertir a secuencial.

4. La última llamada a +parallel():Stream o +sequential():Stream es la que se tiene en cuenta.

5. ¿Cuántos hilos en paralelo? Runtime.getRuntime.availableProcessors()

6. Propiedad: "java.util.concurrent.ForkJoinPool.common.parallelism" modifica valor por defecto

7. El uso de Streams en Paralelo requiere más trabajo, no siempre terminará más rápido que Streams secuenciales.

Page 46: Lambdas y API Stream #PerúJUG #Java20

Stream APIStreams Paralelos - ¿Cuándo usarlos?

Consideraciones a tener en cuenta si se desea usar Streams en Paralelo:

1. Medir primero ● N = Número de items● Q = costo de procesar un item● N*Q = Costo total de las operaciones. Mientras más grande, mejor usar Streams Paralelos

2. Evitar el Autoboxing y Unboxing

3. Algunas operaciones no se comportan bien en paralelo● +limit(long):Stream<T> ● +findFirst():Optional<T> ● +sorted():Stream<T> ● +distinct():Stream<T>

4. Usar estructuras que sean fáciles de descomponer● ArrayList -> Exelente● HashSet, TreeSet -> Bien● LinkedList -> Mal

Page 47: Lambdas y API Stream #PerúJUG #Java20

Enlaces de interés

Java SE 8 API docshttp://download.java.net/jdk8/docs/api/

JDK 8 Downloadhttp://www.oracle.com/technetwork/java/javase/overview/

ArtículosLambdas y API Stream Parte 1Lambdas y API Stream Parte 2

Taller Prácticohttps://github.com/aalopez/lambdas-lab

Java 8 in Actionhttp://www.manning.com/urma/

Page 48: Lambdas y API Stream #PerúJUG #Java20