2

which of the following two snippets is faster, assuming list is an ArrayList.

for(int i=0; i<list.size();i++){...}

or

int count = list.size();
for(int i=0; i<count;i++){...}

Also, does the optimization (if any) carry to Android's ArrayAdapter?

int sCount = mAdapter.getCount();

CLARIFICATION

in the for-loop does the compiler call list.size() each time or does it call it once and use it subsequently.

Note that each call to list.size() will actually go and count the items. So that's the essence of the question.

7
  • 1
    We are talking nanoseconds here...is it really that important? I would think readability should your bigger concern. Commented Sep 23, 2013 at 20:46
  • this iteration takes nanoseconds. but what if it is used in a very heavy algorithm. all efficient snippet of code that handles heavy algorithms depend on such issues. Commented Sep 23, 2013 at 20:48
  • 2
    Profile both solutions, get the results in numbers and find your answer for your specific platform. Still, this is a micro optimization, which does nothing good that taking your real world time. Commented Sep 23, 2013 at 20:48
  • While you're at it you could also initialize i outside of the loop, ala C. Might save you a few picoseconds. Seriously though, they should compile to the same thing. Commented Sep 23, 2013 at 20:49
  • 4
    Note that each call to list.size() will actually go and count the items. So that's the essence of the question. since you say you use an ArrayList as the List implementation, your statement is false. Commented Sep 23, 2013 at 20:53

6 Answers 6

3

In most situations, the speed will be indistinguishable. That said, your two loops are semantically different if the collection might be changing while the loop is executing. The modification of the collection could be in the loop (or in code called in the loop) or in a different thread that is executing concurrently.

To specifically answer your "clarification": yes, the size method will be invoked each time through the loop.

I would never write the "optimized" version of this loop unless I had clear evidence that the optimization was important to do (and the collection isn't changing). If your code is so tuned that such tweaks are giving you measurable speedups, you should be pretty happy.

Sign up to request clarification or add additional context in comments.

2 Comments

The "optimized" version may also be wrong in some cases (multithreaded use of this list as example).
Agreed. Hence the "...your two loops are semantically different..."
2

You should ask yourself some questions:

  • Do I have a perfomance problem?
  • Have I profiled the bottleneck to this code?

If booth questions can be answered wit YES, than try both ways and profile the results.

In fact I think it just won't make a difference.

1 Comment

Finally somebody that focus how the real performance problems must be addressed.
0

Any decent compiler will compile these to the exact same assembly code.

2 Comments

See my clarification section
no, because a) the java compiler makes nearly no optimisation because this will reduce the benefit of the JIT and b) It will cange the behavior
0
int count = list.size();
for(int i=0; i<count;i++){...}// Is faster

6 Comments

And that because it is (or at least: may be) wrong in multithreaded use.
@ChristianKuetbach it is not a matter of multithreading, it is wrong in every case the list is changing in size. But if your list doesn't change, this is a viable optimization, although I would declare count as final.
I think in most cases changing the list while iterating without a iterator() will cause a ConcurrenModificationException :)
@ChristianKuetbach I think that while(!list.isEmpty()) { list.remove(0);} is calling size in a looping construct, changes the underlying datastructure and doesn't throw this exception ;-)
ConcurrenModificationException will occur trying to access iterator and your list at same time. like while looping to iterator and remove elements from list or map.
|
0
    ArrayList list = new ArrayList();
            for(int i=0; i<1000000;i++){
                list.add("Object added "+i);
            }
            long startTime =System.currentTimeMillis();
            for(int i=0; i<list.size();i++){
                System.out.println(list.get(i));
            }
            long endTime = System.currentTimeMillis();




            int count=list.size();
            long startTime1 =System.currentTimeMillis();
            for(int i=0; i<count;i++){
                System.out.println(list.get(i));
            }
            long endTime1 = System.currentTimeMillis();
            System.out.println("Exe1 time in millis secs"+(endTime-startTime));
            System.out.println("Exe2 time in millis secs"+(endTime1-startTime1));

OutPut 
...........
.............

Object added 999999
Exe1 time in millis secs14131
Exe2 time in millis secs14106

2 Comments

You measued the time of "System.out.println()" not the loop. Using System.out is really slow compared to the changes of the list.size(). That is what I meant by "profile". Use profile4j or the eclipse profiler and versify my comment.
Given how insanely slow System.out.println is a 0.1% speed boost actually looks pretty good (assuming its reproducable). Seriously; I've had my full 3D game brought to a stuttering halt by a few print statements
0

I think the second piece of code is slightly faster. A method call may need to load code into memory and will load data from and to the method memory stacks (as in the first piece of code). Which is obviously, slower than a single memory access (first piece of code). However, I think it's safer to use the first piece of code, if the array size may change during the loop iterations. Consider the following example:

for(int i=0; i<list.size();i++){
  if list.get(i) == 0 { list.remove(i); i--; }
}    

The example above remove null elements from the array. Thus, the array size decreases each time an element is deleted. If you don't use list.size() and forget to appropriately update the size of the array, you will end up with "index out of bound" exception.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.