-2
\$\begingroup\$

I use self-closing bodyless for loop to quickly find an element within an array or collection. Learned it from a Java teacher. But I'm seeing warnings on certain IDEs that have a code inspection tool. For example, IntelliJ deems this construct to be a probable bug and objects to the empty body of the loop.

The code below compares a bodied and bodyless for loop on an array with ~9,000 String entries. From the output, it seems that there's a 3 x time advantage in having the for loop bodyless.

But is there a real insecurity in this construct ? I ask as I'm very partial to using it.

   String[] stArray = {"arsch", "a1", "a2", "b1", "c2", "c1",

                        .....................................
                        .....................................
                        .....................................

                         "arsch", "a1", "a2", "b1", "c2", "c1"};

    long startTime1 =  System.nanoTime();

    int i;
    for(i = 0; i < stArray.length; i++)
        if (stArray[i] == "bozo")
            break;
    if (i < stArray.length)
        System.out.println("Item at index #" + i);
    else
        System.out.println("Item not in array.");

    long endTime1 =  System.nanoTime();
    long duration1 = endTime1 - startTime1;


    long startTime2 =  System.nanoTime();

    for(i = 0; i < stArray.length && stArray[i] != "bozo"; i++);
    if (i < stArray.length)
        System.out.println("Item at index #" + i);
    else
        System.out.println("Item not in array.");

    long endTime2 =  System.nanoTime();
    long duration2 = endTime2 - startTime2;

    System.out.println("Duration1: " + duration1);

    System.out.println("Duration2: " + duration2);

    System.out.println("Array Size: " + stArray.length);

OUTPUT
======

Item not in array.
Item not in array.
Duration1: 765700
Duration2: 221000
Array Size: 9132
\$\endgroup\$

closed as off-topic by 200_success, 1201ProgramAlarm, dfhwze, Heslacher, Toby Speight Jul 9 at 7:43

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Lacks concrete context: Code Review requires concrete code from a project, with sufficient context for reviewers to understand how that code is used. Pseudocode, stub code, hypothetical code, obfuscated code, and generic best practices are outside the scope of this site." – 200_success, dfhwze, Toby Speight
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 1
    \$\begingroup\$ The way you have currently formulated the question, it seems to be asking for opinions about a particular looping style, with some code thrown in merely as an example. If you want your code to be reviewed, please describe in detail what specific task it accomplishes, and retitle the question according to the How to Ask guidelines. (Based on my guess at what you want to accomplish, I'm not convinced that the code actually does the job correctly.) \$\endgroup\$ – 200_success Jul 9 at 0:16
  • \$\begingroup\$ I apologize if this is the wrong forum. I'd thought that this forum would have readers who were more knowledgeable in code efficiency. As you suggest, this code is just a demonstration snippet as the method it's used in (a sort of mergeInVocab(. .) method used in text analysis) is really beside the point for this question. \$\endgroup\$ – Trunk Jul 9 at 8:38
  • \$\begingroup\$ Done detailed comparisons with bodyless and bodied for loop plus while loop. Found no significant advantage with bodyless for. Perhaps best not used. \$\endgroup\$ – Trunk Jul 23 at 14:27
2
\$\begingroup\$

IntelliJ reports:

. . . While occasionally intended, this construction is confusing, and often the result of a typo.

I agree with the first part, but it's letting you know about this mainly for the second part. It's pretty common on Stack Overflow to see problems arise from people putting a semicolon in weird places and having odd behavior as a result:

Why does this code only print once?

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

An IDE warning would have given hints as to what the problem was.


Like I said though, I agree with it pointing this out for reasons other than a typo too. I personally find it to read less explicitly. To me, the body represents what the purpose/action of the loop is, and the parenthesized part before the body states the bounds of the problem being dealt with by the loop.

I find your preferred way to be forcing too much onto one line, and I generally find it less clear. The full version is quite explicit (I added braces to avoid a whole other set of problems that IntelliJ likely warned you about):

// Standard index bounds. Nothing to think about
for(i = 0; i < stArray.length; i++) {
    if (stArray[i] == "bozo") {
        break; // Break when i points to "bozo". Easy
    }
}

// Loop while i is in bounds... and i doesn't point to "bozo"
// Oh, break when it points to "bozo"
for(i = 0; i < stArray.length && stArray[i] != "bozo"; i++);

It honestly took me longer to mentally verify the correctness of your shorter version.

Also, what if you wanted to add debugging prints or something else to the loop? You'd need to add a body in that case anyway. And are you going to keep the && stArray[i] != "bozo" part once you have a body?


I'd also take your benchmarking with a grain of salt. Java is not a simple language to do micro-benchmarking on, and it's more likely that your measured speedup is a result of a fluke, or from the first loop having warmed up the JVM first.

\$\endgroup\$
  • \$\begingroup\$ That JetBrains comment [confluence.jetbrains.com/display/GRVY/Inspections] on for-loops reads to me as an admonishment against assignments within the top line of a for statement or empty bodied for-loops. I've seen code where people summed or multiplied an index and I agree it's hazardous and quizzical. \$\endgroup\$ – Trunk Jul 9 at 8:54
  • \$\begingroup\$ Right about JVM sluggishness, @Carci. Just did test on String and int values in an array with up to 100,000,000 entries. Little to choose between bodyless, bodied for loops and the equivalent while. The bodied for loop is ~ 20 ms faster on average for String data and about the same margin slower on int data. Case complete, it seems. \$\endgroup\$ – Trunk Jul 13 at 20:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.