geometricas - ¿Cómo salir de los bucles anidados en Java?
while anidado java (30)
Al igual que en la sugerencia de información de 1800, use la condición que rompe el bucle interno como condición en el bucle externo:
boolean hasAccess = false;
for (int i = 0; i < x && hasAccess == false; i++){
for (int j = 0; j < y; j++){
if (condition == true){
hasAccess = true;
break;
}
}
}
Tengo una construcción de bucle anidado como esta:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
Ahora, ¿cómo puedo salir de ambos bucles? He visto preguntas similares, pero ninguna se refiere específicamente a Java. No pude aplicar estas soluciones porque la mayoría usa gotos.
No quiero poner el bucle interno en un método diferente.
Actualización: no quiero volver a ejecutar los bucles, cuando termine la ruptura, he terminado con la ejecución del bloque de bucle.
Como otros respondedores, definitivamente preferiría poner el bucle interno en un método diferente. Esta respuesta solo muestra cómo se pueden cumplir los requisitos de la pregunta.
Puede utilizar break
con una etiqueta para el bucle exterior. Por ejemplo:
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
Esto imprime:
0 0
0 1
0 2
0 3
0 4
1 0
1 1
1 2
1 3
1 4
2 0
2 1
2 2
2 3
Breaking
Done
Demo para el break
, continue
, label
.
Así que las palabras clave java se break
y continue
tienen un valor predeterminado, es el "Loop más cercano", Toady, unos años después de usar Java, ¡ya lo tengo!
Parece usado raramente, pero útil.
import org.junit.Test;
/**
* Created by cui on 17-5-4.
*/
public class BranchLabel {
@Test
public void test() {
System.out.println("testBreak");
testBreak();
System.out.println("testBreakLabel");
testBreakLabel();
System.out.println("testContinue");
testContinue();
System.out.println("testContinueLabel");
testContinueLabel();
}
/**
testBreak
a=0,b=0
a=0,b=1
a=1,b=0
a=1,b=1
a=2,b=0
a=2,b=1
a=3,b=0
a=3,b=1
a=4,b=0
a=4,b=1
*/
public void testBreak() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
break;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testContinue
a=0,b=0
a=0,b=1
a=0,b=3
a=0,b=4
a=1,b=0
a=1,b=1
a=1,b=3
a=1,b=4
a=2,b=0
a=2,b=1
a=2,b=3
a=2,b=4
a=3,b=0
a=3,b=1
a=3,b=3
a=3,b=4
a=4,b=0
a=4,b=1
a=4,b=3
a=4,b=4
*/
public void testContinue() {
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
if (b == 2) {
continue;
}
System.out.println("a=" + a + ",b=" + b);
}
}
}
/**
testBreakLabel
a=0,b=0,c=0
a=0,b=0,c=1
* */
public void testBreakLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
break anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
/**
testContinueLabel
a=0,b=0,c=0
a=0,b=0,c=1
a=1,b=0,c=0
a=1,b=0,c=1
a=2,b=0,c=0
a=2,b=0,c=1
a=3,b=0,c=0
a=3,b=0,c=1
a=4,b=0,c=0
a=4,b=0,c=1
*/
public void testContinueLabel() {
anyName:
for (int a = 0; a < 5; a++) {
for (int b = 0; b < 5; b++) {
for (int c = 0; c < 5; c++) {
if (c == 2) {
continue anyName;
}
System.out.println("a=" + a + ",b=" + b + ",c=" + c);
}
}
}
}
}
Enfoque bastante inusual, pero en términos de longitud de código ( no de rendimiento ), esto es lo más fácil que podría hacer:
for(int i = 0; i++; i < j) {
if(wanna exit) {
i = i + j; // if more nested, also add the
// maximum value for the other loops
}
}
Incluso creando una bandera para el bucle externo y verificando que después de cada ejecución del bucle interno puede ser la respuesta.
Me gusta esto :
for (Type type : types) {
boolean flag=false;
for (Type t : types2) {
if (some condition) {
// Do something and break...
flag=true;
break; // Breaks out of the inner loop
}
}
if(flag)
break;
}
Java no tiene una función goto como la que hay en C ++. Pero aún así, goto
es una palabra clave reservada en Java. Podrían implementarlo en el futuro. Para su pregunta, la respuesta es que hay algo llamado etiqueta en Java a la que puede aplicar una instrucción continue
y break
. Encuentra el código a continuación:
public static void main(String ...args) {
outerLoop: for(int i=0;i<10;i++) {
for(int j=10;j>0;j--) {
System.out.println(i+" "+j);
if(i==j) {
System.out.println("Condition Fulfilled");
break outerLoop;
}
}
}
System.out.println("Got out of the outer loop");
}
Método mejor y fácil.
outerloop:
for(int i=0; i<10; i++){
// here we can break Outer loop by
break outerloop;
innerloop:
for(int i=0; i<10; i++){
// here we can break innerloop by
break innerloop;
}
}
Necesitaba hacer algo similar, pero elegí no usar el bucle mejorado para hacerlo.
int s = type.size();
for (int i = 0; i < s; i++) {
for (int j = 0; j < t.size(); j++) {
if (condition) {
// do stuff after which you want
// to completely break out of both loops
s = 0; // enables the _main_ loop to terminate
break;
}
}
}
Nunca uso etiquetas. Parece una mala práctica para entrar. Esto es lo que yo haría:
boolean finished = false;
for (int i = 0; i < 5 && !finished; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
finished = true;
break;
}
}
}
Otra solución, mencionada sin ejemplo (realmente funciona en código de producto).
try {
for (Type type : types) {
for (Type t : types2) {
if (some condition #1) {
// Do something and break the loop.
throw new BreakLoopException();
}
}
}
}
catch (BreakLoopException e) {
// Do something on look breaking.
}
Por supuesto, la BreakLoopException
debe ser interna, privada y acelerada con no-stack-trace:
private static class BreakLoopException extends Exception {
@Override
public StackTraceElement[] getStackTrace() {
return new StackTraceElement[0];
}
}
Para algunos casos, podemos usar el bucle while efectivamente aquí.
Random rand = new Random();
// Just an example
for (int k = 0; k < 10; ++k) {
int count = 0;
while (!(rand.nextInt(200) == 100)) {
count++;
}
results[k] = count;
}
Por mucho tiempo pensé en compartir este tipo de respuesta para este tipo de pregunta.
Por lo general, estos casos se encuentran dentro del alcance de una lógica más significativa, digamos algo de búsqueda o manipulación sobre algunos de los objetos iterados en cuestión, por lo que generalmente utilizo el enfoque funcional:
public Object searching(Object[] types) {//or manipulating
List<Object> typesReferences = new ArrayList<Object>();
List<Object> typesReferences2 = new ArrayList<Object>();
for (Object type : typesReferences) {
Object o = getByCriterion(typesReferences2, type);
if(o != null) return o;
}
return null;
}
private Object getByCriterion(List<Object> typesReferences2, Object criterion) {
for (Object typeReference : typesReferences2) {
if(typeReference.equals(criterion)) {
// here comes other complex or specific logic || typeReference.equals(new Object())
return typeReference;
}
}
return null;
}
Cons mayor
- aproximadamente dos veces más líneas
- más consumo de ciclos de computación, lo que significa que es más lento desde el punto de vista algorítmico
- más trabajo de mecanografía
Los profesionales:
- La relación más alta a la separación de preocupaciones debido a la granularidad funcional.
- la mayor relación de reutilización y control de búsqueda / manipulación de lógica sin
- Los métodos no son largos, por lo que son más compactos y fáciles de comprender.
- Proporción subjetivamente más alta de legibilidad
Así que es solo manejar el caso a través de un enfoque diferente.
Básicamente una pregunta al autor de esta pregunta: ¿qué considera usted de este enfoque?
Prefiero agregar una "salida" explícita a las pruebas de bucle. Le deja claro a cualquier lector casual que el bucle puede terminar antes.
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
Puedes hacer lo siguiente:
establecer una variable local en
false
establece esa variable
true
en el primer bucle, cuando quieres romperluego puede verificar en el bucle externo, que si la condición está establecida, entonces también se rompe desde el bucle externo.
boolean isBreakNeeded = false; for (int i = 0; i < some.length; i++) { for (int j = 0; j < some.lengthasWell; j++) { //want to set variable if (){ isBreakNeeded = true; break; } if (isBreakNeeded) { break; //will make you break from the outer loop as well } }
Puedes romper todos los bucles sin usar ninguna etiqueta: y banderas.
Es sólo una solución difícil.
Aquí condición1 es la condición que se utiliza para romper desde el bucle K y J. Y condición2 es la condición que se usa para romper desde el bucle K, J y I.
Por ejemplo:
public class BreakTesting {
public static void main(String[] args) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
for (int k = 0; k < 9; k++) {
if (condition1) {
System.out.println("Breaking from Loop K and J");
k = 9;
j = 9;
}
if (condition2) {
System.out.println("Breaking from Loop K, J and I");
k = 9;
j = 9;
i = 9;
}
}
}
}
System.out.println("End of I , J , K");
}
}
Puedes usar etiquetas:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
Puedes usar un bloque con nombre alrededor de los bucles:
search: {
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break search;
}
}
}
}
Puedes usar una variable temporal:
boolean outerBreak = false;
for (Type type : types) {
if(outerBreak) break;
for (Type t : types2) {
if (some condition) {
// Do something and break...
outerBreak = true;
break; // Breaks out of the inner loop
}
}
}
Dependiendo de su función, también puede salir / regresar del bucle interno:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return;
}
}
}
Quería responder a this pregunta, pero me marcaron como un duplicado que también me impide publicar. Así que publicarlo aquí en su lugar!
Si se trata de una nueva implementación, puede intentar volver a escribir la lógica como si fuesen las instrucciones if-else_if-else.
while(keep_going) {
if(keep_going && condition_one_holds) {
// code
}
if(keep_going && condition_two_holds) {
// code
}
if(keep_going && condition_three_holds) {
// code
}
if(keep_going && something_goes_really_bad) {
keep_going=false;
}
if(keep_going && condition_four_holds) {
// code
}
if(keep_going && condition_five_holds) {
// code
}
}
De lo contrario, puede intentar establecer una bandera cuando haya ocurrido esa condición especial y verificar esa bandera en cada una de sus condiciones de bucle.
something_bad_has_happened = false;
while(something is true && !something_bad_has_happened){
// code, things happen
while(something else && !something_bad_has_happened){
// lots of code, things happens
if(something happened){
-> Then control should be returned ->
something_bad_has_happened=true;
continue;
}
}
if(something_bad_has_happened) { // things below will not be executed
continue;
}
// other things may happen here as well but will not be executed
// once control is returned from the inner cycle
}
HERE! So, while a simple break will not work, it can be made to work using continue.
Si simplemente estás portando la lógica de un lenguaje de programación a Java y solo quieres que funcione, puedes intentar usar labels
Si está dentro de alguna función, ¿por qué no lo devuelves?
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
Si no te gustan los break
s y goto
s, puedes usar un bucle for tradicional en lugar de for-in, con una condición de cancelación adicional:
int a, b;
bool abort = false;
for (a = 0; a < 10 && !abort; a++) {
for (b = 0; b < 10 && !abort; b++) {
if (condition) {
doSomeThing();
abort = true;
}
}
}
Solo usa la etiqueta para romper los bucles internos
public class Test {
public static void main(String[] args) {
outerloop:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
break outerloop;
}
System.out.println(i + " " + j);
}
}
System.out.println("Done");
}
}
Solución Java 8 Stream
:
List<Type> types1 = ...
List<Type> types2 = ...
types1.stream()
.flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2}))
.filter(types -> /**some condition**/)
.findFirst()
.ifPresent(types -> /**do something**/);
Técnicamente la respuesta correcta es etiquetar el bucle exterior. En la práctica, si desea salir en cualquier punto dentro de un bucle interno, sería mejor que externalice el código en un método (un método estático si es necesario) y luego lo llame.
Eso pagaría por la legibilidad.
El código se convertiría en algo así:
private static String search(...)
{
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return search;
}
}
}
return null;
}
Coincidiendo con el ejemplo de la respuesta aceptada:
public class Test {
public static void main(String[] args) {
loop();
System.out.println("Done");
}
public static void loop() {
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking");
return;
}
System.out.println(i + " " + j);
}
}
}
}
Utilice etiquetas.
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
Consulte este artículo
Verifique si el bucle interno se sale con una sentencia if, verificando la variable del bucle interno. También puede crear otra variable como un booleano para verificar si se sale del bucle interno.
En este ejemplo, utiliza la variable del bucle interno para verificar si se ha salido:
int i, j;
for(i = 0; i < 7; i++){
for(j = 0; j < 5; j++) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
if(j < 5){ // Checks if inner loop wasn''t finished
break; // Breaks out of the outer loop
}
}
tal vez con una funcion?
public void doSomething(List<Type> types, List<Type> types2){
for(Type t1 : types){
for (Type t : types2) {
if (some condition) {
//do something and return...
return;
}
}
}
}
for (int j = 0; j < 5; j++) //inner loop
debe reemplazarse por for (int j = 0; j < 5 && !exitloops; j++)
.
Aquí, en este caso, los bucles anidados completos deben salir si la condición es True
. Pero si usamos exitloops
solo para el loop
superior
for (int i = 0; i < 5 && !exitloops; i++) //upper loop
Luego, el bucle interno continuará, porque no hay un indicador adicional que notifique a este bucle interno para salir.
Ejemplo: si
i = 3
yj=2
entonces la condición esfalse
. Pero en la siguiente iteración del bucle internoj=3
entonces la condición(i*j)
convierte en9
cual estrue
pero el bucle interno continuará hasta quej
convierta en5
.
Por lo tanto, debe usar exitloops
para los bucles internos también.
boolean exitloops = false;
for (int i = 0; i < 5 && !exitloops; i++) { //here should exitloops as a Conditional Statement to get out from the loops if exitloops become true.
for (int j = 0; j < 5 && !exitloops; j++) { //here should also use exitloops as a Conditional Statement.
if (i * j > 6) {
exitloops = true;
System.out.println("Inner loop still Continues For i * j is => "+i*j);
break;
}
System.out.println(i*j);
}
}
boolean broken = false; // declared outside of the loop for efficiency
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
broken = true;
break;
}
}
if (broken) {
break;
}
}
boolean condition = false;
for (Type type : types) {
for (int i = 0; i < otherTypes.size && !condition; i ++) {
condition = true; // if your condition is satisfied
}
}
Utilice la condición como indicador para cuando haya terminado de procesar. Entonces, el bucle interno solo continúa mientras no se cumple la condición. De cualquier manera, el bucle exterior se mantendrá en chuggin ''.