Рубрики
Без рубрики

Java ArrayList против LinkedList

Узнайте разницу между ArrayList и LinkedList на Java

Автор оригинала: Mona Mohamadinia.

1. Обзор

Когда дело доходит до коллекции Стандартная библиотека Java предоставляет множество вариантов на выбор. Среди этих вариантов два известных Список реализации, известные как ArrayList и LinkedList, каждый со своими свойствами и использования случаях.

В этом учебнике мы увидим, как эти два на самом деле реализованы. Затем мы оценим различные приложения для каждого из них.

2. ArrayList

Внутренне, ArrayList использует массив для реализации Список интерфейс . Поскольку массивы фиксированного размера в Java, ArrayList создает массив с некоторым первоначальным потенциалом. По пути, если нам нужно хранить больше элементов, чем по умолчанию, он заменит этот массив на новый и более просторный.

Чтобы лучше понять его свойства, давайте оценим эту структуру данных в отношении трех основных операций: добавление элементов , получить один по индексу и удаление по индексным .

2.1. Добавить

Когда мы создаем пустую ArrayList, он инициализирует свой бэк-массив с помощью по умолчанию (в настоящее время 10):

Добавление нового элемента, пока массив еще не заполнен, так же просто, как назначить этот элемент определенному индексу массива. Этот индекс массива определяется текущим размером массива, так как мы практически примыкаем к списку:

backingArray[size] = newItem;
size++;

Итак, в лучших и средних случаях время сложности для операции добавления O(1) , что довольно быстро. Однако по мере полноты резервного массива реализация добавления становится менее эффективной:

Чтобы добавить новый элемент, мы должны сначала инициализировать совершенно новый массив с больше возможностей и скопировать все существующие элементы в новый массив. Только после копирования текущих элементов мы можем добавить новый элемент. Таким образом, сложность времени О(н) в худшем случае, так как мы должны скопировать n элементы в первую очередь.

Теоретически говоря, добавление нового элемента Амортизированной постоянное время. То есть, добавив, n элементы требуют O(n) Время. Тем не менее, некоторые отдельные дополнения могут работать плохо из-за накладных расходов на копию.

2.2. Доступ по индексу

Доступ к товарам по их индексам – это ArrayList действительно светит. Для извлечения элемента на индексной Я, мы просто должны вернуть товар, проживающий в Я й индекс из резервного массива. Следовательно, сложность времени доступа по индексной операции всегда O(1).

2.3. Удалить по индексу

Предположим, мы удалим индекс 6 из нашего ArrayList, что соответствует элементу 15 в нашем резервном массиве:

После маркировки нужного элемента как удаленного, мы должны переместить все элементы после его обратно на один индекс. Очевидно, что чем ближе элемент к началу массива, тем больше элементов мы должны двигаться. Таким образом, сложность времени O(1) в лучшем случае и О(н) в среднем и наихудших случаях.

2.4. Заявки и ограничения

Как правило, ArrayList является выбором по умолчанию для многих разработчиков, когда они нуждаются в Список реализация. На самом деле, это на самом деле разумный выбор, когда количество читает гораздо больше, чем количество .

Иногда нам нужно одинаково часто читать и пишет. Если у нас есть оценка максимального количества возможных элементов, то все равно имеет смысл использовать ArrayList . Если это так, мы можем инициализировать ArrayList с начальной емкостью:

int possibleUpperBound = 10_000;
List items = new ArrayList<>(possibleUpperBound);

Эта оценка может предотвратить множество ненужных копирования и распределения массивов.

Более того, массивы индексируются int значения на Яве. Таким образом, это не возможно хранить больше, чем 2 32 элементы в массиве Java и, следовательно, в ArrayList .

3. Связанный список

LinkedList , как следует из названия, использует коллекцию связанных узлов для хранения и извлечения элементов . Например, вот как выглядит реализация Java после добавления четырех элементов:

Каждый узел поддерживает два указателя: один указывает на следующий элемент, а другой со ссылкой на предыдущий. Расширяя это, вдвойне связанный список имеет два указателя, указывающие на первый и последний элементы.

Опять же, давайте оценим эту реализацию в отношении тех же фундаментальных операций.

3.1. Добавить

Для того, чтобы добавить новый узел, во-первых, мы должны связать текущий последний узел с новым узел:

А затем обновить последний указатель:

Поскольку обе эти операции тривиальны, сложность времени для операции добавления всегда O(1) .

3.2. Доступ по индексу

LinkedList, в отличие от ArrayList, не поддерживает быстрый случайный доступ. Таким образом, для того, чтобы найти элемент по индексу, мы должны пройти некоторую часть списка вручную .

В лучшем случае, когда запрашиваемый элемент находится ближе к началу или концу списка, сложность времени будет так же быстро, как O(1). Тем не менее, в среднем и худшем случае, мы можем в конечном итоге с О(н) время доступа, так как мы должны изучить много узлов один за другим.

3.3. Удалить по индексу

Для того, чтобы удалить элемент, мы должны сначала найти запрошенный элемент, а затем оон-ссылка его из списка . Следовательно, время доступа определяет сложность времени, то есть O(1) в лучшем случае и О(н) в среднем и в наихудших сценариях.

3.4. Заявки

LinkedLists более подходящими, когда скорость добавления намного выше, чем скорость чтения .

Кроме того, он может быть использован в сценариях чтения тяжелых, когда большую часть времени мы хотим первый или последний элемент. Стоит отметить, что LinkedList также реализует Деке интерфейс – поддержка эффективного доступа к обоим концам коллекции.

Как правило, если мы знаем их различия в реализации, то мы могли бы легко выбрать один для конкретного случая использования.

Например, предположим, что мы будем хранить много событий тайм-ряда в структуре данных, похожей на список. Мы знаем, что будем получать всплески событий каждую секунду.

Кроме того, мы должны изучить все события один за другим периодически и предоставить некоторые статистические данные. Для этого случая использования, LinkedList является лучшим выбором, потому что скорость добавления намного выше, чем скорость чтения.

Кроме того, мы хотели бы прочитать все элементы, поэтому мы не можем бить О(н) верхний предел.

4. Заключение

В этом учебнике, во-первых, мы приняли погружение в том, ArrayList и LinkLists реализованы на Java.

Мы также оценивали различные случаи использования для каждого из них.