recorrer lista ejemplos arquitectura algoritmo java foreach lambda java-8

lista - ¿Rompe o regresa del flujo de Java 8 para cada uno?



lambda java 8 ejemplos (11)

Cuando usamos una iteración externa sobre un Iterable , usamos break o return de un bucle mejorado para cada bucle como:

for (SomeObject obj : someObjects) { if (some_condition_met) { break; // or return obj } }

¿Cómo podemos break o return utilizando la iteración interna en una expresión lambda de Java 8 como:

someObjects.forEach(obj -> { //what to do here? })


¿Qué pasa con este?

condición final de BooleanWrapper = new BooleanWrapper ();

someObjects.forEach(obj -> { if (condition.ok()) { // YOUR CODE to control condition.stop(); } });

Donde BooleanWrapper es una clase que debe implementar para controlar el flujo.


A continuación encontrará la solución que utilicé en un proyecto. En lugar de forEach solo usa allMatch :

someObjects.allMatch(obj -> { return !some_condition_met; });


Esto es posible para Iterable.forEach() (pero no de forma confiable con Stream.forEach() ). La solución no es agradable, pero es posible.

ADVERTENCIA : no debe usarlo para controlar la lógica empresarial, sino únicamente para manejar una situación excepcional que se produce durante la ejecución de forEach() . Por ejemplo, como un recurso deja de ser accesible de manera repentina, uno de los objetos procesados ​​está violando un contrato (por ejemplo, el contrato dice que todos los elementos en el flujo no deben ser null sino que repentinamente e inesperadamente uno de ellos es null ), etc.

De acuerdo con la documentación para Iterable.forEach() :

Realiza la acción dada para cada elemento del Iterable hasta que todos los elementos hayan sido procesados ​​o la acción arroje una excepción ... Las excepciones lanzadas por la acción se transmiten al llamante.

Así que lanza una excepción que inmediatamente romperá el bucle interno.

El código será algo así: no puedo decir que me guste, pero funciona. Usted crea su propia clase BreakException que extiende RuntimeException .

try { someObjects.forEach(obj -> { // some useful code here if(some_exceptional_condition_met) { throw new BreakException(); } } } catch (BreakException e) { // here you know that your condition has been met at least once }

Observe que try...catch no está alrededor de la expresión lambda, sino más bien alrededor del método forEach() . Para hacerlo más visible, vea la siguiente transcripción del código que lo muestra con mayor claridad:

Consumer<? super SomeObject> action = obj -> { // some useful code here if(some_exceptional_condition_met) { throw new BreakException(); } }); try { someObjects.forEach(action); } catch (BreakException e) { // here you know that your condition has been met at least once }


He logrado por algo como esto

private void doSomething() { List<Action> actions = actionRepository.findAll(); boolean actionHasFormFields = actions.stream().anyMatch(actionHasMyFieldsPredicate()); if (actionHasFormFields){ context.addError(someError); } } } private Predicate<Action> actionHasMyFieldsPredicate(){ return action -> action.getMyField1() != null; }


No es fácil hacerlo por las API proporcionadas en JDK. Pero podemos hacerlo por AbacusUtil . Aquí está el código de muestra:

Stream.of("a", "b", "c", "d", "e").peek(N::println) // .forEach("", (r, e) -> r + e, (e, r) -> e.equals("c")); // print: a b c

Divulgación: Soy el desarrollador de AbacusUtil.


Para un rendimiento máximo en operaciones paralelas, use findAny () que es similar a findFirst ().

Optional<SomeObject> result = someObjects.stream().filter(obj -> some_condition_met).findAny();

Sin embargo, si se desea un resultado estable, use findFirst () en su lugar.

También tenga en cuenta que los patrones coincidentes (anyMatch () / allMatch) solo devolverán un valor booleano, no obtendrá el objeto coincidente.


Puedes lograr eso usando una mezcla de peek (..) y anyMatch (..).

Usando tu ejemplo:

someObjects.stream().peek(obj -> { <your code here> }).anyMatch(obj -> !<some_condition_met>);

O simplemente escriba un método util genérico:

public static <T> void streamWhile(Stream<T> stream, Predicate<? super T> predicate, Consumer<? super T> consumer) { stream.peek(consumer).anyMatch(predicate.negate()); }

Y luego úsalo, así:

streamWhile(someObjects.stream(), obj -> <some_condition_met>, obj -> { <your code here> });


Puedes usar java8 + rxjava .

//import java.util.stream.IntStream; //import rx.Observable; IntStream intStream = IntStream.range(1,10000000); Observable.from(() -> intStream.iterator()) .takeWhile(n -> n < 10) .forEach(n-> System.out.println(n));


Si necesita esto, no debe usar forEach , sino uno de los otros métodos disponibles en las transmisiones; cual, depende de cual sea tu meta.

Por ejemplo, si el objetivo de este bucle es encontrar el primer elemento que coincida con algún predicado:

Optional<SomeObject> result = someObjects.stream().filter(obj -> some_condition_met).findFirst();

(Nota: Esto no repetirá toda la colección, ya que las secuencias se evalúan perezosamente: se detendrán en el primer objeto que coincida con la condición).

Si solo quieres saber si hay un elemento en la colección para el cual la condición es verdadera, puedes usar anyMatch :

boolean result = someObjects.stream().anyMatch(obj -> some_condition_met);


Un retorno en una lambda equivale a una continuación en una para cada uno, pero no hay equivalente a una ruptura. Usted puede simplemente hacer una devolución para continuar:

someObjects.forEach(obj -> { if (some_condition_met) { return; } })


O bien , debe usar un método que use un predicado que indique si debe seguir adelante (para que tenga la ruptura) o necesita lanzar una excepción, lo cual es un enfoque muy feo, por supuesto.

Así que podrías escribir un método forEachConditional como este:

public static <T> void forEachConditional(Iterable<T> source, Predicate<T> action) { for (T item : source) { if (!action.test(item)) { break; } } }

En lugar de Predicate<T> , es posible que desee definir su propia interfaz funcional con el mismo método general (algo que toma una T y devuelve un bool ) pero con nombres que indican la expectativa con mayor claridad. Predicate<T> no es ideal aquí .