Ao usar a iteração externa sobre um Iterable
nós usamos break
ou return
do aprimorado para cada loop como:
for (SomeObject obj : someObjects) {
if (some_condition_met) {
break; // or return obj
}
}
Como podemos break
ou return
usando a iteração interna em uma expressão lambda do Java 8 como:
someObjects.forEach(obj -> {
//what to do here?
})
for
declaração real .forEach()
. A solução não é boa, mas é possível. Veja minha resposta abaixo.if
condição simples dentro daforEach
solução fará o truque.Respostas:
Se você precisar disso, não deve usar
forEach
, mas um dos outros métodos disponíveis nos fluxos; qual deles depende de qual é seu objetivo.Por exemplo, se o objetivo desse loop for encontrar o primeiro elemento que corresponda a algum predicado:
(Nota: Isso não irá iterar a coleção inteira, porque os fluxos são avaliados preguiçosamente - ele pára no primeiro objeto que corresponde à condição).
Se você quiser apenas saber se há um elemento na coleção para o qual a condição é verdadeira, você pode usar
anyMatch
:fonte
return
declaração de umfindSomething
método.break
é mais comumente associado a um tipo de operação que demora um pouco .forEach
para isso; você deve usar outro método mais apropriado.forEach
" estava tecnicamente incorreta. Também prefiro sua solução, no entanto, posso imaginar casos de uso em que a solução fornecida em minha resposta é preferível: quando o loop deve terminar por causa de uma exceção real . Concordo que você geralmente não deve usar as exceções para controlar o fluxo.Isso é possível para
Iterable.forEach()
(mas não de maneira confiávelStream.forEach()
). A solução não é boa, mas é possível.AVISO : Você não deve usá-lo para controlar a lógica de negócios, mas apenas para lidar com uma situação excepcional que ocorre durante a execução do
forEach()
. Como um recurso repentinamente deixa de ser acessível, um dos objetos processados está violando um contrato (por exemplo, o contrato diz que todos os elementos no fluxo não devem ser, de maneiranull
repentina e inesperada, um deles énull
) etc.De acordo com a documentação para
Iterable.forEach()
:Então você lança uma exceção que interrompe imediatamente o loop interno.
O código será algo assim - não posso dizer que gosto, mas funciona. Você cria sua própria classe
BreakException
que se estendeRuntimeException
.Observe que o não
try...catch
está relacionado à expressão lambda, mas ao redor de todo o método. Para torná-lo mais visível, consulte a seguinte transcrição do código que mostra mais claramente:forEach()
fonte
Stream.forEach
se não fornecer a mesma garantia forte sobre exceções sendo retransmitida para o chamador, então lançar uma exceção não é garantido para trabalhar desta forma paraStream.forEach
.Iterable.forEach()
, mas eu adicionei seu ponto ao meu texto apenas pela integridade.Um retorno em um lambda é igual a um continuar em um para cada, mas não há equivalente a uma interrupção. Você pode simplesmente fazer um retorno para continuar:
fonte
Abaixo você encontra a solução que usei em um projeto. Em vez disso,
forEach
basta usarallMatch
:fonte
Ou você precisa usar um método que use um predicado indicando se deve continuar (para que ele ocorra) ou você deve lançar uma exceção - que é uma abordagem muito feia, é claro.
Então você pode escrever um
forEachConditional
método como este:Em vez disso
Predicate<T>
, convém definir sua própria interface funcional com o mesmo método geral (algo usandoT
ae retornando abool
), mas com nomes que indiquem a expectativa mais claramente -Predicate<T>
não é o ideal aqui.fonte
takeWhile
operação clássica e essa pergunta é apenas uma daquelas que demonstram o quanto sua falta na API do Streams é sentida.Você pode usar o java8 + rxjava .
fonte
Para obter o desempenho máximo em operações paralelas, use findAny (), que é semelhante ao findFirst ().
No entanto, se um resultado estável for desejado, use findFirst ().
Observe também que os padrões correspondentes (anyMatch () / allMatch) retornarão apenas booleanos; você não obterá o objeto correspondente.
fonte
Atualize com Java 9+ com
takeWhile
:fonte
Eu consegui por algo assim
fonte
Você pode conseguir isso usando uma mistura de peek (..) e anyMatch (..).
Usando seu exemplo:
Ou apenas escreva um método util genérico:
E então use-o, assim:
fonte
Que tal este:
Onde
BooleanWrapper
está uma classe que você deve implementar para controlar o fluxo.fonte
!condition.ok()
, no entanto, não impede oforEach()
loop de todos os objetos de qualquer maneira. Se a parte lenta for aforEach()
iteração e não seu consumidor (por exemplo, ela obtém objetos de uma conexão de rede lenta), essa abordagem não é muito útil.Ele fará apenas a operação onde encontrar correspondência e, depois de encontrar correspondência, interrompa sua iteração.
fonte
Eu sugeriria o uso de anyMatch. Exemplo:-
Você pode consultar esta publicação para entender o anyMatch: - https://beginnersbook.com/2017/11/java-8-stream-anymatch-example/
fonte