Gymterview
middle

Предложите эффективный алгоритм удаления нескольких рядом стоящих элементов из середины ArrayList

Самый эффективный способ — использовать метод subList(fromIndex, toIndex).clear(). Внутри он вызывает System.arraycopy() один раз, перемещая все элементы правее удаляемого диапазона на нужное количество позиций влево.

Пример
// Удалить элементы с позиции 100 по 200 (не включая 200)
list.subList(100, 200).clear();

Наивный подход — вызывать remove(index) в цикле N раз — приводит к тому, что каждый remove выполняет свой сдвиг элементов. Это O(N * M), где N — количество удаляемых элементов, M — количество оставшихся справа. subList().clear() делает один сдвиг — O(M).

Пример с замером производительности
import java.util.ArrayList;

public class Main {
    private static final int SIZE = 1_000_000;

    public static void main(String[] args) {
        ArrayList<Integer> list1 = new ArrayList<>(SIZE);
        for (int i = 0; i < SIZE; i++) list1.add(i);

        ArrayList<Integer> list2 = new ArrayList<>(list1);

        // Удаление через remove() — медленно
        long start = System.currentTimeMillis();
        for (int i = 0; i < 20_000; i++) {
            list1.remove(600_000);
        }
        System.out.println("remove() в цикле: " + (System.currentTimeMillis() - start) + " мс");

        // Удаление через subList().clear() — быстро
        start = System.currentTimeMillis();
        list2.subList(600_000, 620_000).clear();
        System.out.println("subList().clear(): " + (System.currentTimeMillis() - start) + " мс");
    }
}

На собеседовании: назовите subList().clear() как оптимальный подход. Объясните, почему он быстрее: один вызов System.arraycopy() вместо N.