Reputation: 2585
This is my Java code:
List<Object> objects = new ArrayList();
// Assign values to objects
...
for (int i = 0; i < objects.size(); i++) {
Object object = objects.get(i);
...
}
I have two questions:
objects.size()
calculated only once before stating the loop, or is it calculated each loop?objects.size()
is calculated each loop, then if other thread change it at the same time without multi-threads protection, the code may be crashed. Am I correct?
Upvotes: 14
Views: 8111
Reputation: 425053
Answers:
objects.size()
is called every loop (whether it is calculated depends on the ArrayList implementation, which you shouldn't care about)Real answer:
You shouldn't have to care, and here's how you don't have to:
foreach
syntax, which means you don't have to use an index etc - it's done for you:for (Object object : objects) {
// do something with each object
}
Upvotes: 16
Reputation: 533530
Notionally the objects.size() could be evaluated on each loop. However, as the method is short it can be inlined and cached as its not a volatile variable. i.e. another thread could change it but there is no guarantee that if it did you would see the change.
A short way to save the size is to use the follow.
for (int i = 0, size = objects.size(); i < size; i++) {
Object object = objects.get(i);
...
}
However if you are concerned that another thread could change the size, this approach only protects you if an object is added. If an object is removed you can still get an exception when you attempt to access the value which is now beyond the end of the list.
Using a CopyOnWriteArrayList avoids these issues (provided you use an Iterator) but makes writes more expensive.
Upvotes: 1
Reputation: 61526
- Is objects.size() calculated only once before stating the loop, or is it calculated each loop?
Each time.
- If objects.size() is calculated each loop, then if other thread change it at the same time without multi-threads protection, the code may be crashed.
Yes. Or at least, you may get a ConcurrentModificationException
, and not have any reasonable way to deal with it.
Please note that this could happen even if you cached objects.size()
, except now the .get()
will fail instead because you are trying to get an index that no longer exists. objects.size()
changes because something is removed from, or added to, the container.
Don't modify collections while you are iterating over them.
Upvotes: 1
Reputation: 30648
yes when you are using objects.size()
inside the loop condition it calculates every time. better way is to keep it in a variable before going into loop;
like int
limit=objects.size();
for (int i = 0; i < limit; i++) {
Object object = objects.get(i);
...
}
If you have another thread it may change it but using the above option it will not affect or crash you programm.
Upvotes: 2
Reputation: 1567
yes , it will calculate each time
if you look into for loop statement, in the first statement it will set counter initial value then it will check for maximum value then it will execute for loop body then after it will increase value of counter and then again check for maximum value. every time to check maximum value it will call size method.
Upvotes: 1
Reputation: 31710
Yes, it is calculated each time. If you have another thread altering the size of your objects list, the loop condition will keep changing.
Upvotes: 9