java foreach lambda java-8 return-type

java 8 foreach return value



Regreso de lambda forEach() en java (4)

Estoy tratando de cambiar algunos for-each loops a lambda forEach() -methods para descubrir las posibilidades de las expresiones lambda. El siguiente parece ser posible:

ArrayList<Player> playersOfTeam = new ArrayList<Player>(); for (Player player : players) { if (player.getTeam().equals(teamName)) { playersOfTeam.add(player); } }

Con lambda forEach()

players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});

Pero el siguiente no funciona:

for (Player player : players) { if (player.getName().contains(name)) { return player; } }

con lambda

players.forEach(player->{if (player.getName().contains(name)) {return player;}});

¿Hay algo mal en la sintaxis de la última línea o es imposible regresar del método forEach() ?


El return allí está regresando de la expresión lambda en lugar del método contenedor. En lugar de forEach , necesitas filter la transmisión:

players.stream().filter(player -> player.getName().contains(name)) .findFirst().orElse(null);

Aquí, el filter restringe la secuencia a los elementos que coinciden con el predicado, y findFirst luego devuelve un Optional con la primera entrada coincidente.

Esto parece menos eficiente que el enfoque for-loop, pero de hecho findFirst() puede findFirst() un cortocircuito: no genera todo el flujo filtrado y luego extrae un elemento del mismo, en lugar de eso filtra solo tantos elementos como necesite para para encontrar la primera coincidencia. También puede usar findAny() lugar de findFirst() si no necesariamente se preocupa de obtener el primer jugador que hace juego de la transmisión (ordenada) sino simplemente cualquier elemento que coincida. Esto permite una mejor eficiencia cuando hay un paralelismo involucrado.



Le sugiero que primero intente comprender Java 8 en toda la imagen, y lo más importante, en su caso serán los streams, las lambdas y las referencias de métodos.

Nunca debe convertir el código existente en código Java 8 línea por línea, debe extraer características y convertirlas.

Lo que identifiqué en su primer caso es el siguiente:

  • Desea agregar elementos de una estructura de entrada a una lista de salida si coinciden con algún predicado.

Veamos cómo lo hacemos, podemos hacerlo con lo siguiente:

List<Player> playersOfTeam = players.stream() .filter(player -> player.getTeam().equals(teamName)) .collect(Collectors.toList());

Lo que haces aquí es:

  1. Convierta su estructura de entrada en una transmisión (supongo que es de tipo Collection<Player> , ahora tiene una Stream<Player> .
  2. Filtra todos los elementos no deseados con un Predicate<Player> , mapeando cada jugador al booleano verdadero si se desea conservar.
  3. Recoge los elementos resultantes en una lista, a través de un Collector , aquí podemos usar uno de los recopiladores de biblioteca estándar, que es Collectors.toList() .

Esto también incorpora otros dos puntos:

  1. Codifique las interfaces, de modo que codifique contra List<E> sobre ArrayList<E> .
  2. Use la inferencia de diamante para el parámetro de tipo en la new ArrayList<>() , está usando Java 8 después de todo.

Ahora en su segundo punto:

Una vez más, desea convertir algo de Java heredado en Java 8 sin mirar la imagen más grande. Esta parte ya ha sido respondida por @IanRoberts , aunque creo que debes hacer players.stream().filter(...)... sobre lo que sugirió.


Si desea devolver un valor booleano, puede usar algo como esto (mucho más rápido que el filtro):

players.stream().anyMatch(player -> player.getName().contains(name));