private void deletePassedItems() {
for (RoadObject el : items) {
if (el.y > RacerGame.HEIGHT) {
items.remove(el);
}
}
}
Коваленко Виталий
29 уровень
Скажите, пожалуйста, зачем для удаления элемента из списка items нужно создавать копию этого списка? Почему нельзя сделать deletePassedItems() как приведено в моем примере?
Решен
Комментарии (11)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
LuneFoxJava Developer в BIFITExpert
6 октября 2020, 20:02
Говоря человеческим языком, коллекция не хочет менять своё содержание, пока прохождение циклом по ней завязано на каждом её элементе. Вдруг что-то пропадёт или добавится, и цикл сломается. Скажем, если добавится один элемент, должен ли цикл по нему тоже проходиться? А если должен, то когда? Сразу или потом? Или придерживаться оригинального списка? А если уберётся один элемент, а цикл хотел по нему пройтись тоже? Надо по нему пройтись и потом удалить, или удалить и не проходиться? Вот из-за этого нельзя менять коллекцию во время прохождения по ней же.
0
hidden #2322530
6 октября 2020, 10:59полезный
можно использовать метод removeif()
либо Iterator / iterator.remove()
+1
Wladyslaw Java Developer Master
6 октября 2020, 10:55решение
Потому что коллекцию нельзя модифицировать когда ты по ней итерируешь. А форич - это неявный итератор.
Можно было бы удалять а цикле, если цикл был бы обычным фором и ты обращался бы к коллекции просто по индексу. Но тогда при модификации нужно было бы следить и за счётчиком цикла тоже.
Там же ещё в первом квесте были задачки, которые должны были показать что такое ConcurrentModificationException
+2
Коваленко Виталий QA Automation Engineer
6 октября 2020, 15:06
спасибо
0
hidden #2322530
6 октября 2020, 20:19
но правда еще можно использовать коллекции concurrent)
и тогда этот код прекрасно отработает:
0
Wladyslaw Java Developer Master
6 октября 2020, 20:54
да, но только нужно понимать что итератор полученный из копионрайт листа - это снапшот коллекции на момент получения итератора. Это может быть приемлемо для твоей логики, а может и не быть. Просто нужно это понимать
+1
hidden #2322530
6 октября 2020, 20:56
полезный коммент. спасибо
0
Wladyslaw Java Developer Master
6 октября 2020, 21:17
кстати - не сработает, увы.
Потому как я тут задумался, а как оно должно срабоать, вот и загуглил. 😀
см. пункт 4.
Хотя, непосредственно методами коллекции - может и сработать, не влияя на данный итератор. Ладно, смотреть надо, а мне лень в данный момент.
0
hidden #2322530
6 октября 2020, 21:20
отлично отработал пример. я его даже проверил перед тем как постить
и да, ты был прав, что он через snapshot работает:
0
Wladyslaw Java Developer Master
6 октября 2020, 21:36
ага, работает.
Но работает потому что снапшот-итератор проверяет свои элементы на кондишин и передает ссылку на объект, который удовлетворяет ему в метод листу, который по иквалсу удаляет объект. Отсутствие исключения нам гарантирует природа итератора копионрайт листа.
А потом у тебя выводится обновленный лист уже посредством другого "цикла". Но вот этот снапшнот-итератор, он никаких изменений не увидит. Вот декомпилированный байт-код, например.
Подозреваю что List.forEach - тот же итератор. Что многое объясняет.
Но утверждать не стану😅
0
hidden #2322530
6 октября 2020, 22:03
тот же. но он по другой коллекции итератор. а там внутри вся логика.
я думаю что мы нашли компромисс в вопросе. если не вдаваться в глубину вопроса. я там не столько компетентен) опыта мало
Iterator() это ведь поддержка интерфейса Iterable
0