views:

176

answers:

9
+2  Q: 

Java While-Loops

So while rewriting some code, I came across something along the lines of:

Method 1

while ( iter.hasNext() ) {
    Object obj = iter.next();
    if ( obj instanceof Something ) {
        returnValue = (Something) obj;
        break;
    }
}

I re-wrote it as the following without much thought (the actual purpose of the re-write was for other logic in this method):

Method 2

while ( (iter.hasNext()) && (returnValue == null) ) {
    Object obj = iter.next();
    if ( obj instanceof Something ) {
        returnValue = (Something) obj;
    }
}

I personally don't have any strong preference for either and really don't see anything wrong with either approach. Can anyone else think of benefits or consequences of using either approach? The variable, returnValue is returned. How would people feel if that was the last block in the method, and it is just returned?

EDIT: So here's what I'm doing: Currently this method takes a set of authorizations and validates them - returning a boolean. This method allows grouping so you can specify that at least one or all (meaning if at least one authorization is valid, pass the whole set). However, this method does not support levels of authorization which is what I'm changing it to do so that each level can specify different grouping. All this bit is just background information...does not have that much to do with the above code - an alternative method is used to perform the above block of code.

+2  A: 

One school of thought is that a method should only have one return statement/point at the end of the method.

I tend to use whatever is clearer in the specific circumstances.

As an aside:

1) Should you be rewriting code that works (assuming it does)?

2) Should you be rewriting code that doesn't have tests (assuming it does not)?

Mitch Wheat
The part that's being re-written is some of the logic before that block, this block was re-written into the 2nd method without being intended. I don't believe there are test cases :(
nevets1219
+7  A: 

I like the first as it is more clear why you are breaking out of the loop. It says "if this condition is true, set the value and break the loop, we're done". The other took me another second or so, but as you said, there is no huge difference.

Ed Swangren
I would argue that the explicit jump is better.
Ravi Wallau
Which is why it is minor and subjective =)
Ed Swangren
+2  A: 

Those are equivalent in this case but that is no longer the case if you want to do something after the if condition, which is often the case.

Performance is a wash and even if it wasn't, it's an irrelevant micro-optimization. The key goal should be readability and maintainability.

cletus
True words, ... +1
Willi
+3  A: 

I prefer the explicit jump (whether it's a break or a return). It's difficult for me to articulate why, but I can compare it to writing in active vs. passive voice. Sure, it's merely style, but active is a lot more straightforward to read.

Cory Petosky
+9  A: 

Clearer, for me, would be to extract this as a method of its own; then you can simply return the value rather than assigning it to a local.

while (iter.hasNext()) {
    Object obj = iter.next();
    if (obj instanceof Something)
        return (Something)obj;
}
return null;

Better yet would be a foreach loop

for (Object o : yourList)
    if (o instanceof Something)
        return (Something)o
return null;
Carl Manaster
I thought of answering this way but it's only equivalent if the original code is followed immediately by a "return returnValue;" (which we don't know). If it _does_ return immediately after, your code is better, despite all the clowns who are likely to complain about multiple return points (who don't realise that's a guideline to keep code readable, not a commandment from on-high). +1 on the assumption that you're correct since this idiom is mostly used in that way.
paxdiablo
@paxdiablo even if there is more going on in the method than this, this part of the method could be extracted into its own method, and called from the original method. Thanks for the support; it took me a while to learn that multiple return points aren't evil.
Carl Manaster
Silly me, I didn't read the last para of the question. It is indeed followed immediately by a return which makes this answer a good one.
paxdiablo
I agree to the way but not to your coding style, sorry. There should be {}s around your blocks.
Willi
I like the idea of extracting the logic into its own method as it applies for many cases and it does for this case as well. Since there's no really right answer, I will accept this based on user votes.
nevets1219
+1  A: 

Method 1 is much clearer in what it is doing, it breaks the loop when obj instanceof Something==true, although method 2 is also pretty obvious. Another slight advantage of Method 1 is that it is slightly faster since method 2 does one more condition check every loop, and it does one more check than method 1. What if the check took more than 1 minute?

So obviously Method 1 is better and easier to understand.

TiansHUo
+1 A valid point!
nevets1219
+1  A: 

Clearly the first form is much better because it is less complex. If you are not doing anything with returnValue you could simply return it as soon as you have found a match.

fastcodejava
+1  A: 

I don't agree that the first form is clearly better... The problem with returns, breaks and continues is that they make the code harder to refactor. The example given here is too simple to require such manipulation but in general it is all too easy to refactor a complex piece of code into its own method and neglect to ensure the caller's return paths remain valid. This is where automated testing can help, but I still prefer most of my checking to come out of the compiler.

I took the approach of asking what the loop is doing - Two things, it checks for the existence of an Object of type Fish, and it makes that Object available outside the loop. If we separate the two responsibilities we get:

Object obj = null;
while (iter.hasNext() && !(obj instanceof Fish)) {
  obj = iter.next();
}
if (obj instanceof Fish) {
  returnValue = (Fish) obj;
}

I still don't like it... perhaps its the instanceof or the use of Object or even just the nature of Iterator but it doesn't seem like nice code.

CurtainDog
The existing logic is: if it is type A do this else do that. I'm making it such that if it is type A do this, type B do that, else something else. I'll edit my question to contain more detail.
nevets1219
+1  A: 

After your edit, it seems that you will have iterate through the whole list to check for all kinds of authorities. The code would be like:

Object returnValue=null; //Notice in your original code
while(iter.hasNext()){
    Object kind=iter.next()
    switch(kind.getType()){
       case "fish": 
       case "reptile":
          if(returnValue!=bird|returnValue!=mammal)
               returnValue=(coldblood) kind;
          break;
       case "bird":
       case "mammal":
          returnValue=(coldblood) kind;
          break;
       case default:
          //Fall-through
    }
}
return returnValue;

So this is what I have to say:

  1. You said you needed to implement multiple levels of permissions, I believe that you will have to iterate through the whole collection.
  2. That having said, I recommend using Method 1 - that is if you have to break. The break keyword is more clear, and it is slightly faster. (One less jump however slight)
TiansHUo
Unfortunately, there's only two cases that I have to check for, everything else is ignored. I resort to walking through the Set when a previously unused method (that doesn't walk through the Set) fails to retrieve the value I'm looking for.
nevets1219