Обход элементов ArrayList
| English | Русский |
|---|---|
| ConcurrentModificationException/kənˈkʌrənt ˌmɒdɪfɪˈkeɪʃn ekˈsepʃn/ | ConcurrentModificationException |
Choose a traversal that matches the intended change
- An ArrayList contains [2, 3, 4]. You want to double every stored value, while keeping the number of elements unchanged.
- An indexed loop can use list.set(i, 2 * list.get(i)). Assigning x = 2*x in for (int x : list) changes only the local loop variable.
Начиная со списка [2, 3, 4], выполните for (int x : list) { x = 2 * x; }. Чему равно list.get(1)?
Присваивание локальной примитивной переменной x не заменяет хранящийся объект Integer. Средний элемент списка остается равным 3.
Looping over a list
- Traverse an ArrayList just like an array, but with its methods. Indexed:
for (int i = 0; i < list.size(); i++) { ... list.get(i) ... } - For-each:
for (String s : list) { ... s ... }— clean for reading values.size()(notlength) bounds the indexed loop.
The same patterns
- Sum, count, min/max, and search all work the same as with arrays. Just swap
a[i]forlist.get(i)anda.lengthforlist.size(). - The accumulator and max/count logic is identical. Everything you learned for array traversal carries over.
Reading vs. modifying
- An enhanced loop copies each element value into its loop variable. For
Integerelements read asint x, assigning toxdoes not replace a list element; an indexed loop can replace it withset(i, x). - For structural changes (adding/removing), use the indexed loop carefully. Reading is simple; removing while looping needs extra care (next lesson).
Подсчет суммы элементов ArrayList по индексу
Граница задается через size(), чтение — через get(i) (list = [10,20,30]).
Правильное условие для цикла по индексу в ArrayList — это...
ArrayList использует size(); массивы используют length.
Why should a program avoid direct structural changes during an ArrayList enhanced-for traversal?
ArrayList fail-fast behaviour is best-effort. Avoid unsafe traversal rather than relying on a guaranteed exception.
Шаблоны обхода массивов (сумма, подсчет, максимум) работают так же для ArrayList.
Просто замените a[i]/a.length на list.get(i)/list.size().
Для безопасного удаления элементов при обходе списка следует использовать...
for-each не может изменять структуру; индексный цикл может (аккуратно).
Без структурных изменений во время обхода улучшенный цикл for-each может прочитать все записи из ArrayList
Цикл читает каждую сохраненную ссылку. Структурные изменения во время обхода — отдельный вопрос; данное утверждение не гарантирует безопасность всех операций над каждым возможным элементом.
Don't modify during for-each
- Adding or removing during a for-each loop may trigger a ConcurrentModificationException 并发修改异常; fail-fast detection is best-effort. The for-each loop assumes the list doesn't change structure underneath it.
- To remove while traversing, use an indexed loop (and manage the index). Reading with for-each is suitable when the list is not structurally changed during traversal. Also check element requirements: unboxing a null Integer still throws an exception.
Bound an indexed ArrayList loop with list.size(), not .length, and never structurally modify during a for-each. Calling add/remove inside a for (x : list) may trigger a ConcurrentModificationException, but detection is not guaranteed. To delete while traversing, use an indexed loop — and remember remove(i) shifts later elements, so don't blindly i++ past the shifted element.
After the indexed doubling update, what is list.get(1)?
The middle stored value 3 is replaced by 6. Reassigning a primitive loop variable would leave it at 3.
Для непустых записей Student вызов s.addScore(5) внутри цикла for (Student s : students) может изменить хранящиеся данные Students без добавления или удаления элементов из списка.
Скопированные ссылки указывают на изменяемые объекты Student. Их поля могут изменяться без изменения структуры списка.
Summing an ArrayList
- Indexed:
for (int i = 0; i < list.size(); i++) { sum += list.get(i); } - For-each:
for (int x : list) { sum += x; }(autoboxing/unboxing handles Integer↔int). - Both total the list; for-each is cleaner for read-only.
Carry the reasoning to a new case
- Adding or removing directly during enhanced traversal is unsafe; fail-fast exceptions are best-effort, not a guaranteed correctness check.
- A list of mutable Student objects can be traversed with
for (Student s : students) { s.addScore(5); }, assuming non-null entries. This changes each object's state without changing list structure; assigning a different reference toswould not replace the stored element.
Traverse an ArrayList with an indexed loop (i < list.size(), list.get(i)) or an enhanced loop that receives each element value. The array patterns (sum, count, min/max, search) all carry over. Avoid direct structural changes during an enhanced traversal: a ConcurrentModificationException may detect the bug, but is not guaranteed. Use a carefully managed indexed loop for the removal pattern taught next; changing a referenced object's fields is different from changing list structure.