Назад к вопросам
Middle
128
questionbank
Что лучше использовать: ArrayList или LinkedList, если я хочу удалить элемент из середины списка?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
ArrayList.
При удалении элемента из середины списка:
- ArrayList: Требует смещения всех последующих элементов, что в худшем случае (при удалении первого элемента) занимает время $О(n)$, где $n$ — количество элементов. Однако, в среднем, операция остается $О(n)$, так как нужно сместить только половину элементов. Фактическая производительность часто выше из-за лучшей локальности данных.
- LinkedList: Требует итерации по элементам до нахождения нужного узла ($O(n)$ в худшем случае, если итерация начинается с начала или конца). После нахождения узла удаление занимает $О(1)$.
Несмотря на то, что удаление самого узла в LinkedList быстрее, поиск узла до удаления делает общую операцию в среднем медленнее, чем в ArrayList.
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class ListRemovalComparison {
public static void main(String[] args) {
int size = 100000; // Размер списка
int removeIndex = size / 2; // Индекс для удаления (середина)
// ArrayList
List<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < size; i++) {
arrayList.add(i);
}
long startTimeArrayList = System.nanoTime();
arrayList.remove(removeIndex); // Удаление из середины
long endTimeArrayList = System.nanoTime();
long durationArrayList = (endTimeArrayList - startTimeArrayList);
System.out.println("Время удаления из ArrayList: " + durationArrayList + " ns");
// LinkedList
List<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < size; i++) {
linkedList.add(i);
}
long startTimeLinkedList = System.nanoTime();
linkedList.remove(removeIndex); // Удаление из середины
long endTimeLinkedList = System.nanoTime();
long durationLinkedList = (endTimeLinkedList - startTimeLinkedList);
System.out.println("Время удаления из LinkedList: " + durationLinkedList + " ns");
}
}
Результаты бенчмарка показывают, что для удаления элемента из середины, ArrayList, как правило, быстрее, несмотря на теоретическую сложность сдвига. Это связано с тем, что поиск элемента по индексу в LinkedList ($O(n)$) выполняется медленнее, чем сдвиг в ArrayList.
// ArrayList - доступ по индексу O(1), удаление O(n) (сдвиг)
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.add("B");
arrayList.add("C");
arrayList.remove(1); // Удаление "B" - требует сдвига "C"
// LinkedList - доступ по индексу O(n), удаление O(1) (после нахождения узла)
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("A");
linkedList.add("B");
linkedList.add("C");
linkedList.remove(1); // Удаление "B" - сначала нужно найти узел "B" (O(n)), затем удалить (O(1))
В итоге, для операции удаления из середины, если вы знаете индекс, ArrayList часто является более предпочтительным выбором из-за более быстрой операции доступа по индексу, что компенсирует затраты на сдвиг.