Хорошо, вот выдержка из источников JDK (src.zip в папке JDK):
public int size() {
return size;
}
Это из ArrayList, но я думаю, что другие коллекции имеют аналогичные реализации.Теперь, если мы представим, что компилятор встроил вызов size () (что имело бы смысл), ваш цикл превращается в следующее:
for(int i=0;i<list.size;i++)
// ...
(Хорошо, давайте забудем, что размер является личным.) КакКомпилятор проверяет, была ли коллекция изменена?Ответ, что это не так и не нужно делать, потому что размер уже доступен в поле, поэтому все, что ему нужно сделать, это получить доступ к полю размера на каждой итерации, но получить доступ к переменной int очень быстро.операция.Обратите внимание, что он, вероятно, вычисляет свой адрес один раз, поэтому ему даже не нужно разыменовывать список на каждой итерации.
Что происходит, когда коллекция изменяется, скажем, методом add ()?
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
Как видите, он просто увеличивает поле размера.Таким образом, компилятору на самом деле не нужно ничего делать, чтобы обеспечить доступ к последнему размеру.Единственным исключением будет то, что если вы изменяете коллекцию из другого потока, вам нужно синхронизировать, иначе поток цикла может увидеть свое локальное кэшированное значение размера, которое может обновляться или не обновляться.