4

I have to iterate with a for-loop, but I want to know which way is better.

1:

import java.util.ArrayList;

public class FindTime {
    public static void main(String[] args) {
        ArrayList tmpList = new ArrayList();
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");

        long startTime = System.nanoTime();
        for (int i = 0,size=tmpList.size(); i < size; i++) {
            System.out.println(tmpList.get(i).toString());
        }
        long endTime = System.nanoTime();

        System.out.println("Time Duration ::->" + (endTime - startTime));
    }
}

2:

import java.util.ArrayList;

public class FindTime {
    public static void main(String[] args) {
        ArrayList tmpList = new ArrayList();
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");
        tmpList.add("me");  tmpList.add("you ");
        tmpList.add("I");   tmpList.add("Us");

        long startTime = System.nanoTime();
        for (int i = 0;i < tmpList.size(); i++) {
            System.out.println(tmpList.get(i).toString());
        }
        long endTime = System.nanoTime();

        System.out.println("Time Duration ::->" + (endTime - startTime));
    }
}

In the above, both for-loops have the same content but just a difference in the loop condition. Can anyone tell me what is actually happening in the above iterations?

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Gabu
  • 83
  • 1
  • 13
  • There is no difference in the loops functionally. The only difference is that in the first case you have an extra condition in your initializer which assigns the size of the list to the variable `size`, which is then used as the upper bound of the loop. In the second case, you also as upper bound the size of the list, but you do so explicitly by calling the list's `size()` method. – Tim Biegeleisen Sep 02 '16 at 04:55
  • Which is easier to read `for (int i = 0,size=tmpList.size(); i < size; i++) {` OR `for (int i = 0;i < tmpList.size(); i++) {` ? – Scary Wombat Sep 02 '16 at 04:56
  • 2
    Most readable would be `for (String s : tmpList) System.out.println(s)`, and it might also be fastest. But to do that you'd need to make `tmpList` an `ArrayList` instead of a raw `ArrayList`. Also, if you're concerned with speed, don't call `toString()` on a `String` which just wastes time. But you probably found that you needed to call `toString()` because you used `ArrayList` instead of `ArrayList`. – ajb Sep 02 '16 at 05:00
  • possible duplicate of http://stackoverflow.com/questions/9336704/jvm-option-to-optimize-loop-statements – Scary Wombat Sep 02 '16 at 05:13
  • It's not clear to me what you mean by better (possibly performance but [GhostCat's answer](http://stackoverflow.com/a/39284623/2654103) raises issues like readability or best-practice). The question could still be more specific. – Linus Sep 02 '16 at 07:11
  • i just want to which for-loop give me less response time and which take more time with reason. – Gabu Sep 02 '16 at 08:19
  • Well, IUknown gave you a crisp answer to that. And I told you with lengthy sentences that you should better focus on a wider scope; and that **response time thoughts** do not **make any sense on this level**. Long story shorty: you wont get much else here. So, better decide which answer to accept and move on. – GhostCat Sep 05 '16 at 11:28
  • internally would be same @ajb,@GhostCat. please check this answer http://stackoverflow.com/questions/28404490/how-does-for-each-loop-works-internally-in-java – Gabu Sep 06 '16 at 08:24

2 Answers2

13

You are getting this all wrong. You are focusing on aspects that almost don't matter; and doing so, you wrote bad code - in both your examples!

First of all, you don't use raw types.

You go for this instead:

List<String> theWords = new ArrayList<>();

( Please note: it is also better practice to use List as actual type of your list object. No need to expose the implementation behind it to users of that list )

And Java has nice ways of "filling" a list, like

List<String> theWords = Arrays.asList("me", "didn't", "know", "that", "but", "could", "have");

Then; you use for-each to iterate all kinds of collections/arrays:

for (String aWord : theWords) 

and you stop worrying about all these low level for loops with ints and increments and stuff.

In other words: Java is not C. We have better abstractions in many places; you better focus on those; as they take care of such subtleties. Meaning: focus on writing "higher level" code - because that creates readable code. And be assured: if you follow the typical "best practices" (as iterating loops using 'for each' like above) - you don't need to worry about performance. Because the JVM and JIT are best at optimizing things ... if you use the abstractions that they offer to you!

Trying to be smart; and expressing things "low level" can even have negative effects; because it might prevent the JIT from doing its glory optimization work (probably not in this case).

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 2
    I would upvote this a 1000 times if I could `focus on writing "higher level" code - because that creates readable code` – Scary Wombat Sep 02 '16 at 05:16
  • I wouldn't mind being it upvoted a thousand times. Thanks; thats nice feedback ;-) – GhostCat Sep 02 '16 at 05:19
  • I want to use for-loop which is provide me less response time, i have thousand of record.check this post http://stackoverflow.com/questions/28404490/how-does-for-each-loop-works-internally-in-java – Gabu Sep 06 '16 at 08:20
  • 1
    And you think the way you iterate matters? Not the reading of data via IO, not the processing, not the "output handling" that your code probably does? **AGAIN: only worry about performance problems that you have PROVEN TO EXIST for example doing exact measurements**. It is really pointless to talk about (for int i) versus (for bla : blub) ... as the **real** cost of handling thousands of thingies ... will not be *iterating* them. And side note: depending on the "size" of your thingies ... "thousands" might mean *nothing* on modern hardware. Again: measure your whole process. – GhostCat Sep 06 '16 at 08:26
  • ... to identify the **true** performance killers. And then focus on them. Instead of wasting hours and hours thinking about (for int ...) vs for (each) – GhostCat Sep 06 '16 at 08:26
4
  • 1 is faster because tmpList.size() is called only once.

  • 2 is cleaner and easier to read because its simpler.

Cleanest

The following is cleanest because its easy to read and has full syntax highlight support in every IDE:

for ( String s : tmpList ) {
    System.out.println(s);
}

Fastest

The following is the fastest performance because it uses a native array and avoids unnessesary object creation and getter method calls:

String[] tmpList = String[24];
tmpList[0] = "me";
tmpList[1] = "you";
...

for ( int i = 0; i < tmpList.length; ++i ) {
    System.out.println(tmpList[i]);
}

Very Fastest

In fact the very fastest performance solution is to unroll your loop if you have a list which is known at compile time.

System.out.println("me");
System.out.println("you");
...

In general KISS (keep it simple stupid) and optimize only when you face a real performance problem.

IUnknown
  • 73
  • 1
  • 7
  • The fastest would probably be to use a `StringBuilder` or `String.join` to concatenate the Strings to a single one and print it at once. The overhead of `System.out.println` may well be worth it. (But, as always, you can't be sure unless you profile). – Hulk Sep 02 '16 at 09:10
  • 1
    In that particular example yes. I had the impresseion that the question was about speeding up loop iteration, so i just wanted to notice about loop unrolling, which is a common practice in high-performance applications. – IUnknown Sep 02 '16 at 09:27