Skip to content

Instantly share code, notes, and snippets.

@dferrandizmont
Last active December 17, 2018 14:38
Show Gist options
  • Save dferrandizmont/aabcd73e3c2df0423671c3dee8c3424f to your computer and use it in GitHub Desktop.
Save dferrandizmont/aabcd73e3c2df0423671c3dee8c3424f to your computer and use it in GitHub Desktop.
[Java 8] Java 8 cheatsheet #java

JAVA 8 - Chuleta

Expresión Lambda

(int a) -> a * 2; // Calcula el doble de a
a -> a * 2; // o simplemente sin tipo
(a, b) -> a + b; // Suma 2 parametros

Si lambda tiene mas de una expresión podemos usar { } y return

(x, y) -> {
	int sum = x + y;
	int avg = sum / 2;
	return avg;
}

Una expresión lambda no puede usarse sola en Java, necesita estar asociada a un interfaz funcional

interface MyMath {
    int getDoubleOf(int a);
}
	
MyMath d = a -> a * 2; // asociado a un interfaz
d.getDoubleOf(4); // es 8

Todos los ejemplos con "list" usan:

List<String> list = [Bohr, Darwin, Galilei, Tesla, Einstein, Newton]

Colecciones

sort sort(list, comparator)

list.sort((a, b) -> a.length() - b.length())
list.sort(Comparator.comparing(n -> n.length())); // igual
list.sort(Comparator.comparing(String::length)); // igual
//> [Bohr, Tesla, Darwin, Newton, Galilei, Einstein]

removeIf

list.removeIf(w -> w.length() < 6);
//> [Darwin, Galilei, Einstein, Newton]

merge merge(key, value, remappingFunction)

Map<String, String> names = new HashMap<>();
names.put("Albert", "Ein?");
names.put("Marie", "Curie");
names.put("Max", "Plank");

// El valor "Albert" existe
// {Marie=Curie, Max=Plank, Albert=Einstein}
names.merge("Albert", "stein", (old, val) -> old.substring(0, 3) + val);

// El valor  "Newname" no existe
// {Marie=Curie, Newname=stein, Max=Plank, Albert=Einstein}
names.merge("Newname", "stein", (old, val) -> old.substring(0, 3) + val);

Expresión de metodo Class::staticMethod

Permite referenciar métodos (y constructores) sin ejecutarlos

// Con Lambda:
getPrimes(numbers, a -> StaticMethod.isPrime(a));

// Metodo Referenciado:
getPrimes(numbers, StaticMethod::isPrime);
Método Referenciado Forma de Lambda
StaticMethod::isPrime n -> StaticMethod.isPrime(n)
String::toUpperCase (String w) -> w.toUpperCase()
String::compareTo (String s, String t) -> s.compareTo(t)
System.out::println x -> System.out.println(x)
Double::new n -> new Double(n)
String[]::new (int n) -> new String[n]

Streams

Similares a las colecciones, pero:

  • No almacenan su propia información
  • La información viene de otra parte (colleciones, archivos, db, web, ...)
  • immutable (crean un nuevo stream)
  • lazy (solo computa lo que es necesario !)
// Computara 3 "filter"
Stream<String> longNames = list
   .filter(n -> n.length() > 8)
   .limit(3);

Crea un nuevo stream

Stream<Integer> stream = Stream.of(1, 2, 3, 5, 7, 11);
Stream<String> stream = Stream.of("Jazz", "Blues", "Rock");
Stream<String> stream = Stream.of(myArray); // or from an array
list.stream(); // or from a list

// Stream infinito [0; inf[
Stream<Integer> integers = Stream.iterate(0, n -> n + 1);

Resultado de las colecciones

// Collect into an array (::new is the constructor reference)
// Colecciona en un array (::new es la referencia del contructor)
String[] myArray = stream.toArray(String[]::new);

// Collecciona en un List o Set
List<String> myList = stream.collect(Collectors.toList());
Set<String> mySet = stream.collect(Collectors.toSet());

// Collecciona en un String
String str = list.collect(Collectors.joining(", "));

map map(mapper)
Aplica una función a cada elemento

// Aplica "toLowerCase" a cada elemento
res = stream.map(w -> w.toLowerCase());
res = stream.map(String::toLowerCase);
//> bohr darwin galilei tesla einstein newton

res = Stream.of(1,2,3,4,5).map(x -> x + 1);
//> 2 3 4 5 6

filter filter(predicado)
Retiene elementos que coinciden con el predicado

// Filtra elementos que empiecen con "E"
res = stream.filter(n -> n.substring(0, 1).equals("E"));
//> Einstein

res = Stream.of(1,2,3,4,5).filter(x -> x < 3);
//> 1 2

reduce
Reduce los elementos a un unico valor

String reduced = stream
	.reduce("", (acc, el) -> acc + "|" + el);
//> |Bohr|Darwin|Galilei|Tesla|Einstein|Newton

limit limit(maxSize) Los n primeros elementos

res = stream.limit(3);
//> Bohr Darwin Galilei

skip Descarta los primeros n elementos

res = strem.skip(2); // skip Bohr and Darwin
//> Galilei Tesla Einstein Newton

distinct Borra los elementos repetidos

res = Stream.of(1,0,0,1,0,1).distinct();
//> 1 0

sorted Ordena elementos (debe ser Comparable)

res = stream.sorted();
//> Bohr Darwin Einstein Galilei Newton Tesla 

allMatch

// Comprueba si hay una "e" en cada elemento
boolean res = words.allMatch(n -> n.contains("e"));

anyMatch: Comprueba si hay una "e" en algun elemento
noneMatch: Comprueba si no hay una "e" en ningun elemento

parallel Devuelve un stream equivalente que es paralelo

findAny Mas rapido que findFirst en un stream paralelo

Streams de tipo primitivo

Los wrappers (como Stream) son ineficientes. Requieren de embalar y desembalar cada elemento demasiado. Mejor usar IntStream, DoubleStream, etc.

Creacion

IntStream stream = IntStream.of(1, 2, 3, 5, 7);
stream = IntStream.of(myArray); // de un array
stream = IntStream.range(5, 80); // rango de 5 a 80

Random gen = new Random();
IntStream rand = gen(1, 9); // stream de aleatorios

Usa mapToX (mapToObj, mapToDouble, etc.) si la función produce un valor Object, double, etc.

Resultados agrupados

Collectors.groupingBy

// Agrupados por longitud
Map<Integer, List<String>> groups = stream
	.collect(Collectors.groupingBy(w -> w.length()));
//> 4=[Bohr], 5=[Tesla], 6=[Darwin, Newton], ...

Collectors.toSet

// Igual que antes pero en un Set
... Collectors.groupingBy(
	w -> w.substring(0, 1), Collectors.toSet()) ...

Collectors.counting Cuenta el numero de elementos en una coleccion

Collectors.summing__ summingInt, summingLong, summingDouble para sumar valores de un grupo

Collectors.averaging__ averagingInt, averagingLong, ...

// Longitud promedio de cada elemento de un grupo
Collectors.averagingInt(String::length)

PS: No olvides Optional (como Map<T, Optional<T>>) con algunos metodos de Colecciones (like Collectors.maxBy).

Streams Paralelos

Creacion

Stream<String> parStream = list.parallelStream();
Stream<String> parStream = Stream.of(myArray).parallel();

unordered Pueden acelerar el limit o distinct

stream.parallelStream().unordered().distinct();

PS: Trabaja con la librería de streams. Pe: usa filter(x -> x.length() < 9) en vez de forEach con unif.

Optional

En Java, es común usar null para denotar ausencia de resultado. Problemas cuando no se comprueban: NullPointerException.

// Optional<String> contiene un string o nada
Optional<String> res = stream
   .filter(w -> w.length() > 10)
   .findFirst();

// longitud de res o "", si no trae nada
int length = res.orElse("").length();

// lanza el lambda si no trae nada
res.ifPresent(v -> results.add(v));

Devuelve un Optional

Optional<Double> squareRoot(double x) {
   if (x >= 0) { return Optional.of(Math.sqrt(x)); }
   else { return Optional.empty(); }
}

Note en la inferencia de la limitación

interface Pair<A, B> {
    A first();
    B second();
}

Un stream de tipo Stream<Pair<String, Long>> :

  • stream.sorted(Comparator.comparing(Pair::first)) // vale
  • stream.sorted(Comparator.comparing(Pair::first).thenComparing(Pair::second)) // no funciona

Java no puede inferir el tipo para la parte de .comparing(Pair::first)y devolver el Objeto, por lo que Pair::first no podría ser aplicado.

El tipo requerido para toda la expresión no puede ser propagada a través de la llamada del método (.thenComparing) y ser usada para inferir el tipo de la primera parte.

El tipo debe ser dado explicitamente

stream.sorted(
    Comparator.<Pair<String, Long>, String>comparing(Pair::first)
    .thenComparing(Pair::second)
) // ok

Esta cheat sheet esta basada en la lección de Cay Horstmann http://horstmann.com/heig-vd/spring2015/poo/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment