Вопрос с собеседования · Java

Какие способы удалить элементы по условию во время обхода коллекции корректны?

MiddleКоллекции
Коротко

Корректно: removeIf, явный Iterator.remove(), проход по индексам с конца. Удаление в for-each — CME, по индексам вперёд — пропуск элементов.

  • removeIf на ArrayList — один сдвиг хвоста, а не на каждое удаление
  • iterator.remove синхронизирует ожидаемый modCount
  • Новый список через stream().filter() — тоже вариант

А ещё Для Map — entrySet().removeIf или values().removeIf

Подробно

Метод iterator.remove() работает потому, что итератор сам синхронизирует свой ожидаемый счётчик модификаций с коллекцией. removeIf — самый читаемый вариант и в реализациях на массиве ещё и эффективнее серии удалений, так как сдвигает хвост один раз, а не на каждый элемент. Обход по индексам с конца корректен потому, что удаление сдвигает только элементы правее текущего, которые уже обработаны. Прямое удаление через коллекцию внутри for-each — та самая ошибка, дающая ConcurrentModificationException.

Что хотят услышать

  • Перечень корректных способов и почему они работают.

Частые ошибки

  • Идти по индексам вперёд и удалять — каждый второй элемент будет пропущен.
  • Вызывать iterator.remove() до первого next() — получите IllegalStateException.

Проверьте себя

Несколько верных вариантов. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓collection.removeIf(predicate)
  • ✓Явный Iterator и вызов iterator.remove()
  • ✓Обход списка по индексам с конца к началу
  • ✗for-each с вызовом collection.remove(element)

Что спросят дальше

  • Почему removeIf эффективнее серии remove у ArrayList?
  • Что вернёт stream().filter() — изменит ли он исходную коллекцию?

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования