Reputation: 24639
I've got a nested loop construct like this:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
Now how can I break out of both loops? I've looked at similar questions, but none concerns Java specifically. I couldn't apply these solutions because most used gotos.
I don't want to put the inner loop in a different method.
I don't want to return the loops. When breaking I'm finished with the execution of the loop block.
Upvotes: 2096
Views: 1452793
Reputation: 2227
I never use labels. It seems like a bad practice to get into. Here's what I would do:
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;
}
}
}
By having flag variable ,We can easily control execution of any number of loops ,Just we need to keep this flag value check at loop condition statement as done in main loop->i < 5 && !finished.
Upvotes: 162
Reputation: 174
If someone is looking for the kotlin way of adding labeled loops
loop@ for (i in 1..100) {
for (j in 1..100) {
if (...) break@loop
}
}
Upvotes: 1
Reputation: 794
Using 'break' keyword alone is not the appropriate way when you need to exit from more than one loops. You can exit from immediate loop No matter with how many loops your statement is surrounded with. You can use 'break' with a label! Here I've used the label "abc" You can write your code as following, within any function in Java
This code shows how to exit from the most outer loop
abc:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
Also you can use break statement to exit from any loop in a nested loop.
for (int i = 0; i < 10; i++) {
abc:for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
The following code shows an example of exiting from the innermost loop. In other works,after executing the following code, you are at the outside of the loop of 'k' variables and still inside the loop of 'j' and 'i' variables.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break;
}
}
}
}
Upvotes: 22
Reputation: 9009
It's fairly easy to use label
, You can break the outer loop from inner loop using the label, Consider the example below,
public class Breaking{
public static void main(String[] args) {
outerscope:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
break outerscope;
}
}
}
}
}
Another approach is to use the breaking variable/flag to keep track of required break. consider the following example.
public class Breaking{
public static void main(String[] args) {
boolean isBreaking = false;
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
isBreaking = true;
break;
}
}
if(isBreaking){
break;
}
}
}
}
However, I prefer using the first approach.
Upvotes: 6
Reputation: 4313
Demo
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
Upvotes: 9
Reputation: 2426
Usually in such cases, it is coming in scope of more meaningful logic, let's say some searching or manipulating over some of the iterated 'for'-objects in question, so I usually use the functional approach:
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;
}
Major cons:
The pros:
So it is just handling the case via a different approach.
Basically a question to the author of this question: what do you consider of this approach?
Upvotes: 9
Reputation: 663
Below is an example where "break" statement pushes the cursor out of the for loop whenever the condition is met.
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!!!!!");
}
}
}
Upvotes: 1
Reputation: 1873
Labeled break concept is used to break out nested loops in java, by using labeled break you can break nesting of loops at any position. Example 1:
loop1:
for(int i= 0; i<6; i++){
for(int j=0; j<5; j++){
if(i==3)
break loop1;
}
}
suppose there are 3 loops and you want to terminate the loop3: Example 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;
}
}
}
Upvotes: 10
Reputation: 1268
Demo for break
, continue
, and label
:
Java keywords break
and continue
have a default value. It's the "nearest loop", and today, after a few years of using Java, I just got it!
It's seem used rare, but useful.
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);
}
}
}
}
}
Upvotes: 4
Reputation: 2608
If it's a new implementation, you can try rewriting the logic as if-else_if-else statements.
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
}
}
Otherwise you can try setting a flag when that special condition has occured and check for that flag in each of your loop-conditions.
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.
}
HERE! So, while a simple break will not work, it can be made to work using continue
.
If you are simply porting the logic from one programming language to Java and just want to get the thing working you can try using labels.
Upvotes: 2
Reputation: 463
I feel using labels makes the code seem very much like a goto statement. This is just a thought.
Instead, throw an exception at the inner for
loop and encapsulate the two for
loops with a try catch block.
Something like
try {
// ...
for(Object outerForLoop : objectsOuter) {
// ...
for (Object innerForLoop : objectsInner) {
// ...
if (isConditionTrue)
throw new WrappedException("With some useful message. Probably some logging as well.");
}
}
catch (WrappedException) {
// Do something awesome or just don't do anything to swallow the exception.
}
Just a thought. I prefer this code since it gives me better loggability (like that's a word) for me when this is being run in production or something.
Upvotes: -10
Reputation: 1255
boolean condition = false;
for (Type type : types) {
for (int i = 0; i < otherTypes.size && !condition; i ++) {
condition = true; // If your condition is satisfied
}
}
Use condition
as a flag for when you are done processing. Then the inner loop only continues on while the condition has not been met. Either way, the outer loop will keep on chuggin'.
Upvotes: 1
Reputation: 3517
Even creating a flag for the outer loop and checking that after each execution of the inner loop can be the answer.
Like this:
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;
}
Upvotes: 0
Reputation: 19702
Use a function:
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;
}
}
}
}
Upvotes: 47
Reputation: 1503140
Like other answerers, I'd definitely prefer to put the loops in a different method, at which point you can just return to stop iterating completely. This answer just shows how the requirements in the question can be met.
You can use break
with a label for the outer loop. For example:
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");
}
}
This prints:
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
Upvotes: 2775
Reputation: 149
Java does not have a goto feature like there is in C++. But still, goto
is a reserved keyword in Java. They might implement it in the future. For your question, the answer is that there is something called label in Java to which you can apply a continue
and break
statement. Find the code below:
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");
}
Upvotes: 2
Reputation: 4601
Another one solution, mentioned without example (it actually works in prod code).
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.
}
Of course BreakLoopException
should be internal, private and accelerated with no-stack-trace:
private static class BreakLoopException extends Exception {
@Override
public StackTraceElement[] getStackTrace() {
return new StackTraceElement[0];
}
}
Upvotes: 5
Reputation: 3299
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**/);
Upvotes: 10
Reputation: 2576
Use Labels.
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
Refer to this article
Upvotes: 6
Reputation: 1786
I prefer to add an explicit "exit" to the loop tests. It makes it clear to any casual reader that the loop may terminate early.
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
Upvotes: 11
Reputation: 8570
Like @1800 INFORMATION suggestion, use the condition that breaks the inner loop as a condition on the outer loop:
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;
}
}
}
Upvotes: 2
Reputation: 3218
Rather unusual approach but in terms of code length (not performance) this is the easiest thing you could do:
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
}
}
Upvotes: 5
Reputation: 130
Best and Easy Method..
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;
}
}
Upvotes: 5
Reputation: 3268
You can use labels:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
Upvotes: 128
Reputation: 6876
for (int j = 0; j < 5; j++) //inner loop
should be replaced with
for (int j = 0; j < 5 && !exitloops; j++)
.
Here, in this case complete nested loops should be exit if condition is True
. But if we use exitloops
only to the upper loop
for (int i = 0; i < 5 && !exitloops; i++) //upper loop
Then inner loop will continues, because there is no extra flag that notify this inner loop to exit.
Example : if
i = 3
andj=2
then condition isfalse
. But in next iteration of inner loopj=3
then condition(i*j)
become9
which istrue
but inner loop will be continue tillj
become5
.
So, it must use exitloops
to the inner loops too.
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);
}
}
Upvotes: 3
Reputation: 41
For some cases, We can use while
loop effectively here.
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;
}
Upvotes: 1
Reputation: 1129
You can do the following:
set a local variable to false
set that variable true
in the first loop, when you want to break
then you can check in the outer loop, that whether the condition is set then break from the outer loop as well.
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
}
}
Upvotes: 1
Reputation: 2667
I needed to do a similar thing, but I chose not to use the enhanced for loop to do it.
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;
}
}
}
Upvotes: 13
Reputation: 850
If it is inside some function why don't you just return it:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
Upvotes: 5
Reputation: 4941
You can break from all loops without using any label: and flags.
It's just tricky solution.
Here condition1 is the condition which is used to break from loop K and J. And condition2 is the condition which is used to break from loop K , J and I.
For example:
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");
}
}
Upvotes: 8