ArrayList и LinkedList — это две наиболее часто используемые реализации интерфейса List
в Java. Они имеют разные внутренние структуры данных и, как следствие, разные характеристики производительности. Давайте разберем, чем они отличаются и в каких сценариях предпочтительнее использовать каждый из них.
ArrayList основан на динамическом массиве. Это означает, что элементы хранятся в непрерывном блоке памяти, что обеспечивает быстрый доступ по индексу.
LinkedList основан на двусвязном списке. Каждый элемент (узел) содержит ссылки на предыдущий и следующий элементы, что позволяет эффективно вставлять и удалять элементы в середине списка.
Характеристика | ArrayList | LinkedList |
---|---|---|
Структура данных | Динамический массив | Двусвязный список |
Доступ по индексу | O(1) — быстрый доступ по индексу | O(n) — медленный доступ по индексу |
Вставка/удаление в начале/середине | O(n) — медленно, так как требует сдвига элементов | O(1) — быстро, так как требует только изменения ссылок |
Вставка/удаление в конце | O(1) — быстро, если не требуется увеличение массива | O(1) — быстро |
Использование памяти | Меньше, так как хранит только данные | Больше, так как хранит данные и ссылки |
Итерация | Быстрее, так как элементы хранятся в непрерывной памяти | Медленнее, так как требует перехода по ссылкам |
ArrayList
будет более эффективным.ArrayList
использует меньше памяти, так как не хранит ссылки на соседние элементы.ArrayList
будет эффективным.Пример:
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
String element = list.get(1); // Быстрый доступ по индексу
list.add("D"); // Быстрое добавление в конец
LinkedList
будет более эффективным.LinkedList
поддерживает интерфейсы Deque
и Queue
, что делает его подходящим для реализации структур данных, таких как стеки и очереди.LinkedList
может быть более предпочтительным из-за эффективности операций вставки и удаления.Пример:
List<String> list = new LinkedList<>();
list.add("A");
list.add("B");
list.add("C");
list.add(1, "X"); // Быстрая вставка в середину
list.remove(2); // Быстрое удаление из середины
List<Integer> arrayList = new ArrayList<>();
List<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < 100000; i++) {
arrayList.add(i);
linkedList.add(i);
}
long startTime = System.nanoTime();
arrayList.get(50000);
long endTime = System.nanoTime();
System.out.println("ArrayList access time: " + (endTime - startTime) + " ns");
startTime = System.nanoTime();
linkedList.get(50000);
endTime = System.nanoTime();
System.out.println("LinkedList access time: " + (endTime - startTime) + " ns");
Результат:
ArrayList
будет значительно быстрее, так как доступ по индексу выполняется за O(1).LinkedList
будет медленнее, так как доступ по индексу выполняется за O(n).startTime = System.nanoTime();
arrayList.add(50000, 999);
endTime = System.nanoTime();
System.out.println("ArrayList insert time: " + (endTime - startTime) + " ns");
startTime = System.nanoTime();
linkedList.add(50000, 999);
endTime = System.nanoTime();
System.out.println("LinkedList insert time: " + (endTime - startTime) + " ns");
Результат:
ArrayList
будет медленнее, так как вставка требует сдвига элементов.LinkedList
будет быстрее, так как вставка требует только изменения ссылок.ArrayList:
LinkedList:
Выбор между ArrayList
и LinkedList
зависит от конкретных требований вашего приложения. Для большинства сценариев, где требуется частый доступ по индексу и хранение большого количества данных, ArrayList
будет предпочтительным выбором. Однако, если ваше приложение часто вставляет или удаляет элементы в середине списка, LinkedList
может быть более подходящим.