variable type practices parameter lambdas functional expressions expresiones best advanced java lambda java-8 functional-programming nested-if

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());

Ver http://ideone.com/EOBiEP


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