85

I was wondering if it is a "bad practice" to use a break statement to exit a loop instead of fulfilling the loop condition?

I do not have enough insight in Java and the JVM to know how a loop is handled, so I was wondering if I was overlooking something critical by doing so.

The focus of this question: is there a specific performance overhead?

Don
  • 1,428
  • 3
  • 15
  • 31
  • 13
    i don't hink it is a bad practice as 'break's is meant for that only – Android Killer Aug 12 '13 at 13:24
  • 19
    What would be bad practice, would be to loop 1 million times even if you could have exited after 5 iterations... – assylias Aug 12 '13 at 13:24
  • 2
    personally i think its depends on situation, sometimes using break can increase readability of code, and i don't think in that situations you can call it bad practice – user902383 Aug 12 '13 at 13:32
  • 2
    It is considered bad practice because it can lead to many unwanted situations like exiting loop/method after creating stream and not closing it. But if you use it carefully then it is OK. – Pshemo Aug 12 '13 at 13:32
  • 3
    Basically, you can replace any `break` with an `if` around the whole rest of the code. That's how it is done in some other languages which fascistically follow the "structured programming" paradigm. The code looks awful. – Marko Topolnik Aug 12 '13 at 13:32
  • @Pshemo This is not a reason to avoid `break`; it is one of the many reasons to make use of [RAII](http://c2.com/cgi/wiki?ResourceAcquisitionIsInitialization). – zwol Aug 12 '13 at 15:59
  • @AndroidKiller - Well yes, but `goto` was designed with the sole purpose of jumping to a defined label in code, and in most languages its usage is the definition of bad code. I think the distinction here is that `break` was not only defined for the specific purpose of terminating loops early in the middle of loop code, but is the only way to accomplish said purpose without using `goto`. – KeithS Aug 12 '13 at 16:29
  • Don't forget the keyword "continue" as well. It is similar to a break. – djangofan Aug 14 '13 at 21:58

13 Answers13

140

Good lord no. Sometimes there is a possibility that something can occur in the loop that satisfies the overall requirement, without satisfying the logical loop condition. In that case, break is used, to stop you cycling around a loop pointlessly.

Example

String item;

for(int x = 0; x < 10; x++)
{
    // Linear search.
    if(array[x].equals("Item I am looking for"))
    {
       //you've found the item. Let's stop.
       item = array[x];
       break; 
    }
}

What makes more sense in this example. Continue looping to 10 every time, even after you've found it, or loop until you find the item and stop? Or to put it into real world terms; when you find your keys, do you keep looking?

Edit in response to comment

Why not set x to 11 to break the loop? It's pointless. We've got break! Unless your code is making the assumption that x is definitely larger than 10 later on (and it probably shouldn't be) then you're fine just using break.

Edit for the sake of completeness

There are definitely other ways to simulate break. For example, adding extra logic to your termination condition in your loop. Saying that it is either loop pointlessly or use break isn't fair. As pointed out, a while loop can often achieve similar functionality. For example, following the above example..

while(x < 10 && item == null)
{
    if(array[x].equals("Item I am looking for"))
    {
        item = array[x];
    }

    x++;
}

Using break simply means you can achieve this functionality with a for loop. It also means you don't have to keep adding in conditions into your termination logic, whenever you want the loop to behave differently. For example.

for(int x = 0; x < 10; x++)
{
   if(array[x].equals("Something that will make me want to cancel"))
   {
       break;
   }
   else if(array[x].equals("Something else that will make me want to cancel"))
   {
       break;
   }
   else if(array[x].equals("This is what I want"))
   {
       item = array[x];
   }
}

Rather than a while loop with a termination condition that looks like this:

while(x < 10 && !array[x].equals("Something that will make me want to cancel") && 
                !array[x].equals("Something else that will make me want to cancel"))
christopher
  • 26,815
  • 5
  • 55
  • 89
  • The OP also asked about something akin to setting x to 1000 to break the loop/ – nanofarad Aug 12 '13 at 13:28
  • 5
    What about a while loop instead of a break? Then all loop completion conditions are right at the start of the loop. `while(x < 10 && item == null)` of if you're feeling fancy, use an iterator. – Freiheit Aug 12 '13 at 13:45
  • @Freiheit : you can use it or even you may improve it. But I think example given by `Chris` is for OP's understanding. – Nandkumar Tekale Aug 12 '13 at 13:53
  • 1
    @hexafraction : what if I want to use `x` index in code below the loop? e.g. `found string at index x` – Nandkumar Tekale Aug 12 '13 at 13:55
  • @NandkumarTekale Then you'll need to declare it outside and break out of the loop with it intact. – nanofarad Aug 12 '13 at 13:56
  • @hexafraction `for(int X = foo;X <= Integer.MAX_VALUE;X++) {..}` – Izkata Aug 12 '13 at 13:57
  • @Izkata X should be lowercase as per naming conventions. Also, why are you telling me this? – nanofarad Aug 12 '13 at 13:59
  • @hexafraction : I mean setting x to 1000 wouldn't work in above case – Nandkumar Tekale Aug 12 '13 at 14:00
  • @hexafraction : what value would you set to break the `Izkata's provided loop`? – Nandkumar Tekale Aug 12 '13 at 14:01
  • @NandkumarTekale I wouldn't. I just said the OP asked about it. – nanofarad Aug 12 '13 at 14:01
  • @hexafraction There is no value above MAX_VALUE that will end the loop. (and capitalization is a habit for me for index variables; I'm mostly self-taught, but know not to do it at work) – Izkata Aug 12 '13 at 14:01
  • @Izkata I never said I would do that. I said the OP wanted to do that in a loop that doesn't necessarily reach MAX_VALUE. – nanofarad Aug 12 '13 at 14:02
  • Don't forget the possibility that there might exist no iterator variable at all, or there may be a small multiple of them, or an interator variable exists but is not part of the continuation condition. Constructs like `for(int i=0; myCondition(y); i++) {}` can occasionally be useful, and the most readable way to break out of them (especially if myCondition() is expensive) can easily be a `break`. I figure it's best to use whatever tool is best suited for the job; sometimes a `break` in the middle of a loop makes things clearer, and that's when I use it. – user Aug 12 '13 at 14:12
  • @Izkata Strawman argument. Just because it's possible to write loops whose condition is `true` (`X <= Integer.MAX_VALUE` is just a different way of writing `true`) doesn't mean `break` is needed to write programs. – Sebastian Redl Aug 12 '13 at 14:13
  • Of course, you can do this with a `for` without break as well: http://pastie.org/9545812 Clean, simple, makes the termination conditions stated up front and not buried in the logic. (I'm not one of those "don't use break" people, don't get the wrong idea.) – T.J. Crowder Sep 11 '14 at 19:24
  • That's a cool workaround :) I wouldn't write code like this. I don't think it's quite as easy to follow. – christopher Sep 11 '14 at 20:07
  • I think you can avoid the use of elses in cases like this. You could just do something like: for(...){ if(condition) break; If(condition2) break; //do things you should do inside this loop } – Anderson Silva Oct 21 '15 at 12:42
21

Using break, just as practically any other language feature, can be a bad practice, within a specific context, where you are clearly misusing it. But some very important idioms cannot be coded without it, or at least would result in far less readable code. In those cases, break is the way to go.

In other words, don't listen to any blanket, unqualified advice—about break or anything else. It is not once that I've seen code totally emaciated just to literally enforce a "good practice".

Regarding your concern about performance overhead, there is absolutely none. At the bytecode level there are no explicit loop constructs anyway: all flow control is implemented in terms of conditional jumps.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
6

The JLS specifies a break is an abnormal termination of a loop. However, just because it is considered abnormal does not mean that it is not used in many different code examples, projects, products, space shuttles, etc. The JVM specification does not state either an existence or absence of a performance loss, though it is clear code execution will continue after the loop.

However, code readability can suffer with odd breaks. If you're sticking a break in a complex if statement surrounded by side effects and odd cleanup code, with possibly a multilevel break with a label(or worse, with a strange set of exit conditions one after the other), it's not going to be easy to read for anyone.

If you want to break your loop by forcing the iteration variable to be outside the iteration range, or by otherwise introducing a not-necessarily-direct way of exiting, it's less readable than break.

However, looping extra times in an empty manner is almost always bad practice as it takes extra iterations and may be unclear.

nanofarad
  • 40,330
  • 4
  • 86
  • 117
5

In my opinion a For loop should be used when a fixed amount of iterations will be done and they won't be stopped before every iteration has been completed. In the other case where you want to quit earlier I prefer to use a While loop. Even if you read those two little words it seems more logical. Some examples:

for (int i=0;i<10;i++) {
    System.out.println(i);
}

When I read this code quickly I will know for sure it will print out 10 lines and then go on.

for (int i=0;i<10;i++) {
    if (someCondition) break;
    System.out.println(i);
}

This one is already less clear to me. Why would you first state you will take 10 iterations, but then inside the loop add some extra conditions to stop sooner?

I prefer the previous example written in this way (even when it's a little more verbose, but that's only with 1 line more):

int i=0;
while (i<10 && !someCondition) {
    System.out.println(i);
    i++;
}

Everyone who will read this code will see immediatly that there is an extra condition that might terminate the loop earlier.

Ofcourse in very small loops you can always discuss that every programmer will notice the break statement. But I can tell from my own experience that in larger loops those breaks can be overseen. (And that brings us to another topic to start splitting up code in smaller chunks)

ChristopherS
  • 853
  • 4
  • 16
  • 2
    This doesn't take into account the situation where a condition is reached DURING the for or while loop. If the for/while loop triggers a condition (or perhaps something being executed on another thread) then you may have to break early. The while loop you wrote assumes that you only have to check the condition at the beginning of an iteration. – Doc Aug 12 '13 at 14:09
  • I totally agree with this. If you have a for loop, the intention is that the logic for the initialisation, condition and increment are together in one place. This saves having to look here there and everywhere to find exactly what may be going on. If you do not know how many times you are wanting to loop, then you are looping "while" something, therefore it should be a while loop. If you are looping until something, it should be a do while. I am not suggesting at all that breaks are bad practise, but there is a time and a place for them. – ThePerson Mar 13 '14 at 12:16
  • Why do you have ```For``` and ```While``` capitalized? – Junglemath Apr 13 '22 at 14:40
4

No, it is not a bad practice to break out of a loop when if certain desired condition is reached(like a match is found). Many times, you may want to stop iterations because you have already achieved what you want, and there is no point iterating further. But, be careful to make sure you are not accidentally missing something or breaking out when not required.

This can also add to performance improvement if you break the loop, instead of iterating over thousands of records even if the purpose of the loop is complete(i.e. may be to match required record is already done).

Example :

for (int j = 0; j < type.size(); j++) {
        if (condition) {
            // do stuff after which you want 

            break; // stop further iteration
        }

}
Ankur Shanbhag
  • 7,746
  • 2
  • 28
  • 38
4

Using break in loops can be perfectly legitimate and it can even be the only way to solve some problems.

However, it's bad reputation comes from the fact that new programmers usually abuse it, leading to confusing code, especially by using break to stop the loop in conditions that could have been written in the loop condition statement in the first place.

bluehallu
  • 10,205
  • 9
  • 44
  • 61
  • I see this way too often. I gag every time a see code that initializes looping variables, opens the loop with `while(true)`, then `break`s on some condition. – John Aug 12 '13 at 15:51
  • 1
    @John while sometimes abused there is nothing wrong with that, some idioms require that while(true)...break . For instance, event loops, where the exit condition does not cleanly fit in the conditional, and you may want to do different processing depending on the signal before you break. – crasic Aug 12 '13 at 16:48
3

It isn't bad practice, but it can make code less readable. One useful refactoring to work around this is to move the loop to a separate method, and then use a return statement instead of a break, for example this (example lifted from @Chris's answer):

String item;

for(int x = 0; x < 10; x++)
{
    // Linear search.
    if(array[x].equals("Item I am looking for"))
    {
        //you've found the item. Let's stop.
        item = array[x];
        break; 
    }
}

can be refactored (using extract method) to this:

public String searchForItem(String itemIamLookingFor)
{
    for(int x = 0; x < 10; x++)
    {
        if(array[x].equals(itemIamLookingFor))
        {
            return array[x];
        }
    }
}

Which when called from the surrounding code can prove to be more readable.

robjohncox
  • 3,639
  • 3
  • 25
  • 51
3

There are a number of common situations for which break is the most natural way to express the algorithm. They are called "loop-and-a-half" constructs; the paradigm example is

while (true) {
    item = stream.next();
    if (item == EOF)
        break;
    process(item);
}

If you can't use break for this you have to repeat yourself instead:

item = stream.next();
while (item != EOF) {
    process(item);
    item = stream.next();
}

It is generally agreed that this is worse.

Similarly, for continue, there is a common pattern that looks like this:

for (item in list) {
    if (ignore_p(item))
        continue;
    if (trivial_p(item)) {
        process_trivial(item);
        continue;
    }
    process_complicated(item);
}

This is often more readable than the alternative with chained else if, particularly when process_complicated is more than just one function call.

Further reading: Loop Exits and Structured Programming: Reopening the Debate

zwol
  • 135,547
  • 38
  • 252
  • 361
2

If you start to do something like this, then I would say it starts to get a bit strange and you're better off moving it to a seperate method that returns a result upon the matchedCondition.

boolean matched = false;
for(int i = 0; i < 10; i++) {
    for(int j = 0; j < 10; j++) {
        if(matchedCondition) {
            matched = true;
            break;
        }
    }
    if(matched) {
        break;
    }
}

To elaborate on how to clean up the above code, you can refactor, moving the code to a function that returns instead of using breaks. This is in general, better dealing with complex/messy breaks.

public boolean  matches()
    for(int i = 0; i < 10; i++) {
        for(int j = 0; j < 10; j++) {
            if(matchedCondition) {
                return true;
            }
        }
    }
    return false;
}

However for something simple like my below example. By all means use break!

for(int i = 0; i < 10; i++) {
    if(wereDoneHere()) { // we're done, break.
        break;
    }
}

And changing the conditions, in the above case i, and j's value, you would just make the code really hard to read. Also there could be a case where the upper limits (10 in the example) are variables so then it would be even harder to guess what value to set it to in order to exit the loop. You could of course just set i and j to Integer.MAX_VALUE, but I think you can see this starts to get messy very quickly. :)

Kenny Cason
  • 12,109
  • 11
  • 47
  • 72
  • The "separate method" refactoring deserved emphasis. If you're concerned that a section of code is becoming difficult to read for any reason, extracting it into its own method may help. In the context of this question it also can transform the `break` statements into `return` statements. – Russell Silva Aug 12 '13 at 15:37
  • 1
    @RussellSilva Thanks, I'll edit to add emphasis. – Kenny Cason Aug 12 '13 at 15:44
  • Your first case could be simplified with a break to label. Some people don't like it because it feels like a `goto`, but this is one of the cases where that's particularly useful. – Darrel Hoffman Aug 12 '13 at 16:18
  • @DarrelHoffman You could certainly do that, but I think making it into a seperate method and returning, is the more "standard" way of handling this, at least in Java. – Kenny Cason Aug 12 '13 at 22:33
1

No, it is not a bad practice. It is the most easiest and efficient way.

user2550754
  • 884
  • 8
  • 15
  • 4
    But it might also be the least readable way. Blanket statements like this are usually false in *a significant subset* of cases. – Stephen C Aug 12 '13 at 13:28
  • It depends on your `logic`. Sometimes, you want to abnormally terminate a loop based on some flag or something. In that case, `break` is a good option. – user2550754 Aug 12 '13 at 13:32
1

While its not bad practice to use break and there are many excellent uses for it, it should not be all you rely upon. Almost any use of a break can be written into the loop condition. Code is far more readable when real conditions are used, but in the case of a long-running or infinite loop, breaks make perfect sense. They also make sense when searching for data, as shown above.

Avery
  • 2,270
  • 4
  • 33
  • 35
1

If you know in advance where the loop will have to stop, it will probably improve code readability to state the condition in the for, while, or `do-while loop.

Otherwise, that's the exact use case for break.

peterp
  • 3,101
  • 3
  • 22
  • 37
1

break and continue breaks the readability for the reader, although it's often useful. Not as much as "goto" concept, but almost.

Besides, if you take some new languages like Scala (inspired by Java and functional programming languages like Ocaml), you will notice that break and continue simply disappeared.

Especially in functional programming, this style of code is avoided:

Why scala doesn't support break and continue?

To sum up: break and continueare widely used in Java for an imperative style, but for any coders that used to practice functional programming, it might be.. weird.

Mik378
  • 21,881
  • 15
  • 82
  • 180