J'ai une construction de boucle imbriquée comme ceci:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
Maintenant, comment puis-je sortir des deux boucles? J'ai examiné des questions similaires, mais aucune ne concerne spécifiquement Java. Je ne pouvais pas appliquer ces solutions parce que les gotos les plus utilisés.
Je ne veux pas mettre la boucle intérieure dans une méthode différente.
Je ne veux pas refaire les boucles. En cassant j'ai fini avec l'exécution du bloc de boucle.
Comme d’autres répondeurs, j’aurais définitivement préféré de mettre les boucles d’une autre manière, auquel cas vous pouvez simplement revenir pour arrêter complètement d’itérer. Cette réponse montre simplement comment les exigences de la question peuvent être satisfaites.
Vous pouvez utiliser break
avec une étiquette pour la boucle externe. Par exemple:
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");
}
}
Cela 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
Techniquement, la bonne réponse consiste à étiqueter la boucle externe. En pratique, si vous voulez quitter n'importe quel point de la boucle interne, vous feriez mieux d'extérioriser le code dans une méthode (une méthode statique si besoin est) et de l'appeler.
Cela serait rentable pour la lisibilité.
Le code deviendrait quelque chose comme ça:
private static String search(...)
{
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return search;
}
}
}
return null;
}
Correspondant à l'exemple pour la réponse acceptée:
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);
}
}
}
}
Vous pouvez utiliser un bloc nommé autour des boucles:
search: {
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break search;
}
}
}
}
Je n'utilise jamais d'étiquettes. Cela semble être une mauvaise pratique. Voici ce que je ferais:
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;
}
}
}
Vous pouvez utiliser des étiquettes:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
Utilisez une fonction:
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;
}
}
}
}
Vous pouvez utiliser une variable temporaire:
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
}
}
}
Selon votre fonction, vous pouvez également quitter/revenir de la boucle interne:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
return;
}
}
}
Si vous n'aimez pas break
s et goto
s, vous pouvez utiliser une boucle for "traditionnelle" à la place de for-in, avec une condition d'abandon supplémentaire:
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;
}
}
}
J'avais besoin de faire la même chose, mais j'ai choisi de ne pas utiliser la boucle for améliorée.
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;
}
}
}
Je préfère ajouter une "sortie" explicite aux tests de boucle. Cela indique clairement à tout lecteur occasionnel que la boucle peut se terminer plus tôt.
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
Java 8 Stream
solution:
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**/);
Vous pouvez rompre avec toutes les boucles sans utiliser d’étiquette, ni d’indicateur.
C'est juste une solution délicate.
Ici, condition1 est la condition utilisée pour rompre les boucles K et J ..__ et la condition2 est celle utilisée pour rompre les boucles K, J et I.
Par exemple:
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");
}
}
Habituellement, dans de tels cas, cela relève d'une logique plus significative, par exemple, une recherche ou une manipulation sur certains des objets 'for' en itération en question, c'est pourquoi j'utilise habituellement l'approche fonctionnelle:
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;
}
Contre majeur:
Les pros:
Il s’agit donc simplement de traiter le cas par une approche différente.
Fondamentalement, une question à l'auteur de cette question: que considérez-vous de cette approche?
Meilleure et facile méthode ..
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;
}
}
Si elle se trouve dans une fonction, pourquoi ne pas la renvoyer:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
Approche plutôt inhabituelle mais en termes de longueur de code ( pas de performance ), c’est la chose la plus simple que vous puissiez faire:
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
}
}
Utilisez des étiquettes.
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
Reportez-vous à cet article
Une autre solution, mentionnée sans exemple (cela fonctionne réellement dans le code prod).
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.
}
Bien entendu, BreakLoopException
devrait être interne, privé et accéléré avec no-stack-trace:
private static class BreakLoopException extends Exception {
@Override
public StackTraceElement[] getStackTrace() {
return new StackTraceElement[0];
}
}
Démo pour break
, continue
et label
:
Les mots clés Java break
et continue
ont une valeur par défaut. C'est la "boucle la plus proche" et aujourd'hui, après quelques années d'utilisation de Java, je viens de l'obtenir!
Il semble être utilisé rare, mais utile.
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);
}
}
}
}
}
for (int j = 0; j < 5; j++) //inner loop
doit être remplacé par for (int j = 0; j < 5 && !exitloops; j++)
.
Ici, dans ce cas, les boucles imbriquées complètes doivent être fermées si la condition est True
. Mais si nous utilisons exitloops
uniquement vers le haut loop
for (int i = 0; i < 5 && !exitloops; i++) //upper loop
Ensuite, la boucle interne continuera, car il n'y a pas d'indicateur supplémentaire qui indique à cette boucle interne de quitter.
Exemple: si
i = 3
etj=2
, alors la condition estfalse
. Mais lors de la prochaine itération de la boucle internej=3
, la condition(i*j)
devient9
, qui esttrue
, mais la boucle interne continue jusqu'à ce quej
devienne5
.
Donc, il doit aussi utiliser exitloops
pour les boucles internes.
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);
}
}
Comme dans la suggestion @ 1800 INFORMATION, utilisez la condition qui casse la boucle interne en tant que condition de la boucle externe:
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;
}
}
}
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;
}
}
S'il s'agit d'une nouvelle implémentation, vous pouvez essayer de réécrire la logique comme des instructions 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
}
}
Sinon, vous pouvez essayer de définir un indicateur lorsque cette condition spéciale est remplie et de rechercher cet indicateur dans chacune de vos conditions de boucle.
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) { // The things below will not be executed
continue;
}
// Other things may happen here as well, but they will not be executed
// once control is returned from the inner cycle.
}
ICI! Ainsi, même si une simple pause ne fonctionnera pas, vous pouvez le faire en utilisant continue
.
Si vous portez simplement la logique d’un langage de programmation à Java et que vous voulez que tout fonctionne, essayez d’utiliser labels .
Labeled Break Le concept est utilisé pour diviser les boucles imbriquées en Java. En utilisant la commande label, vous pouvez interrompre l’imbrication des boucles à n’importe quel emplacement. Exemple 1:
loop1:
for(int i= 0; i<6; i++){
for(int j=0; j<5; j++){
if(i==3)
break loop1;
}
}
supposons qu'il y ait 3 boucles et que vous vouliez terminer la boucle3: Exemple 2:
loop3:
for(int i= 0; i<6; i++){
loop2:
for(int k= 0; k<6; k++){
loop1:
for(int j=0; j<5; j++){
if(i==3)
break loop3;
}
}
}
démo
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
Vous pouvez faire ce qui suit:
définir une variable locale sur false
définir cette variable true
dans la première boucle, lorsque vous souhaitez interrompre
vous pouvez ensuite vérifier dans la boucle externe que la condition est définie puis la rompre également.
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
}
}
Dans certains cas, nous pouvons utiliser la boucle while
de manière efficace ici.
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;
}
Même créer un drapeau pour la boucle externe et vérifier qu'après chaque exécution de la boucle interne peut être la réponse.
Comme ça:
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;
}
Vérifiez si la boucle interne est sortie avec une instruction if, en vérifiant la variable de la boucle interne. Vous pouvez également créer une autre variable, telle qu'un booléen, pour vérifier si la boucle interne est sortie.
Dans cet exemple, il utilise la variable de la boucle interne pour vérifier si elle a été quittée:
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
}
}
Vous venez d'utiliser l'étiquette pour casser les boucles intérieures
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");
}
}
Voici un exemple où une instruction "break" fait sortir le curseur de la boucle for dès que la condition est remplie.
public class Practice3_FindDuplicateNumber {
public static void main(String[] args) {
Integer[] inp = { 2, 3, 4, 3, 3 };
Integer[] aux_arr = new Integer[inp.length];
boolean isduplicate = false;
for (int i = 0; i < aux_arr.length; i++) {
aux_arr[i] = -1;
}
outer: for (int i = 0; i < inp.length; i++) {
if (aux_arr[inp[i]] == -200) {
System.out.println("Duplicate Found at index: " + i + " Carrying value: " + inp[i]);
isduplicate = true;
break outer;
} else {
aux_arr[inp[i]] = -200;
}
}
for (Integer integer : aux_arr) {
System.out.println(integer);
}
if (isduplicate == false) {
System.out.println("No Duplicates!!!!!");
} else {
System.out.println("Duplicates!!!!!");
}
}
}
Java n'a pas de fonctionnalité goto comme en C++. Néanmoins, goto
est un mot clé réservé en Java. Ils pourraient le mettre en œuvre à l'avenir. Pour répondre à votre question, la réponse est qu’il existe un élément appelé étiquette auquel vous pouvez appliquer une instruction continue
et break
. Trouvez le code ci-dessous:
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");
}
boolean condition = false;
for (Type type : types) {
for (int i = 0; i < otherTypes.size && !condition; i ++) {
condition = true; // If your condition is satisfied
}
}
Utilisez condition
comme indicateur lorsque vous avez terminé le traitement. Ensuite, la boucle interne continue uniquement tant que la condition n'a pas été remplie. Dans les deux cas, la boucle externe continuera de fonctionner.