type - java lambdas best practices
¿Cómo realizar sentencias anidadas ''if'' usando Java 8/lambda? (5)
Tengo el siguiente código y me gustaría implementarlo usando las funciones lambda solo por diversión. ¿Se puede hacer utilizando las operaciones agregadas básicas?
List<Integer> result = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
if (10 % i == 0) {
result.add(i);
if (i != 5) {
result.add(10 / i);
}
}
}
Usando lambda:
List<Integer> result = IntStream.rangeClosed(1, 10)
.boxed()
.filter(i -> 10 % i == 0)
// a map or forEach function here?
// .map(return 10 / i -> if i != 5)
.collect(Collectors.toList());
Intenta usar flatMap
:
List<Integer> result = IntStream.rangeClosed(1, 10)
.boxed()
.flatMap((i) -> {
List<Integer> results = new ArrayList<>();
if (10 % i == 0) {
results.add(i);
if (i != 5) {
results.add(10 / i);
}
}
return results.stream();
})
.collect(Collectors.toList());
La observación esencial aquí es que su problema implica una transformación no isomórfica : un solo elemento de entrada puede asignarse a cero, uno o dos elementos de salida. Siempre que note esto, debe comenzar a buscar inmediatamente una solución que implique flatMap
lugar de un map
ya que es la única forma de lograr una transformación tan general. En su caso particular, primero puede aplicar el filter
para un mapeo de elementos de uno a cero, luego flatMap
para el flatMap
de uno a dos:
List<Integer> result =
IntStream.rangeClosed(1, 10)
.filter(i -> 10 % i == 0)
.flatMap(i -> i == 5 ? IntStream.of(i) : IntStream.of(i, 10 / i))
.boxed()
.collect(toList());
Podrías declarar un cuerpo para una lambda. Por ejemplo:
Runnable run = () -> System.out.println("Hey");
Podría ser
Runnable run = () -> {
System.out.println("Hey");
};
Dentro de ese cuerpo, puedes crear sentencias anidadas:
Runnable run = () -> {
int num = 5;
if(num == 5) {
System.out.println("Hey");
}
};
Puedes hacerlo:
List<Integer> result1 = IntStream
.rangeClosed(1, 10)
.boxed()
.filter(i -> 10 % i == 0)
.map(i -> (i != 5 ? Stream.of(i, 10 / i) : Stream.of(i)))
.flatMap(Function.identity())
.collect(Collectors.toList());
Use flatMap
mientras intenta agregar elementos a la tubería o un mapeo de 1 a muchos. El mapa es un mapeo uno a uno.
ArrayList<Integer> result = (ArrayList<Integer>) IntStream.rangeClosed(1, 10)
.boxed()
.filter(i -> 10 % i == 0)
.flatMap((Integer i) -> {return i!=5 ? Stream.of(i, (10/i)):Stream.of(i);})
.collect(Collectors.toList());
Esto resulta en la misma lista que
ArrayList<Integer> result2 = new ArrayList<Integer>();
for (int i = 1; i <= 10; i++) {
if (10 % i == 0) {
result2.add(i);
if (i != 5) {
result2.add(10 / i);
}
}
}
En caso de que se pregunte de qué manera es más rápido, el método de bucle es ~ 3 veces más rápido que el uso de flujos.
Benchmark Mode Cnt Score Error Units
testStreams.Bench.loops avgt 5 75.221 ± 0.576 ns/op
testStreams.Bench.streams avgt 5 257.713 ± 13.125 ns/op