Когда использовать LinkedList поверх ArrayList в Java?

2684

Я всегда был один, чтобы просто использовать:

List<String> names = new ArrayList<>();

Я использую интерфейс как имя типа для переносимости, поэтому, когда я задаю такие вопросы, я могу переработать свой код.

Когда следует использовать LinkedList над ArrayList и наоборот?

Теги:
arraylist
collections
linked-list

34 ответа

2810
Лучший ответ

Резюме ArrayList с ArrayDeque предпочтительнее в гораздо большем количестве случаев использования, чем LinkedList. Если вы не уверены - начните с ArrayList.


LinkedList и ArrayList - это две разные реализации интерфейса List. LinkedList реализует его с дважды связанным списком. ArrayList реализует его с помощью динамически изменяющегося массива.

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

Для LinkedList<E>

  • get(int index) - O (n) (с средним значением n/4)
  • add(E element) - O (1)
  • add(int index, E element) - O (n) (с средним значением n/4), но O (1), когда index = 0 <--- главное преимущество LinkedList<E>
  • remove(int index) - O (n) (при среднем числе n/4)
  • Iterator.remove() - O (1). <--- главное преимущество LinkedList<E>
  • ListIterator.add(E element) - это O (1) Это одно из основных преимуществ LinkedList<E>

Примечание: для выполнения многих операций требуется в среднем n/4 шага в среднем, постоянное количество шагов (например, индекс = 0) и n/2 шага в худшем случае (в середине списка)

Для ArrayList<E>

  • get(int index) - O (1) <--- главное преимущество ArrayList<E>
  • add(E element) является O (1) амортизированным, но O (n) наихудшим, так как массив должен быть изменен и скопирован
  • add(int index, E element) - это O (n) (с n/2 шагами в среднем)
  • remove(int index) - это O (n) (с в среднем n/2 шага)
  • Iterator.remove() - O (n) (с n/2 шагами в среднем)
  • ListIterator.add(E element) - это O (n) (при среднем числе n/2 шага)

Примечание: для многих операций требуется среднее число шагов в среднем, постоянное количество шагов в лучшем случае (конец списка), n шагов в худшем случае (начало списка)

LinkedList<E> позволяет устанавливать или удалять постоянное время с использованием итераторов, но только последовательный доступ к элементам. Другими словами, вы можете перемещать список вперед или назад, но поиск позиции в списке занимает время, пропорциональное размеру списка. Javadoc говорит: "Операции, которые индексируют в список, будут пересекать список с начала или конца, в зависимости от того, что ближе", поэтому эти методы в среднем равны O (n) (n/4 шага), хотя O (1) для index = 0.

ArrayList<E>, с другой стороны, допускает быстрый случайный доступ к чтению, поэтому вы можете захватывать любой элемент в постоянное время. Но добавление или удаление из любого места, кроме конца, требует смещения всех последних элементов, чтобы сделать открытие или заполнить пробел. Кроме того, если вы добавляете больше элементов, чем емкость базового массива, выделяется новый массив (в 1,5 раза больше размера), а старый массив копируется в новый, поэтому добавление в ArrayList - это O (n) в наихудший случай, но постоянный в среднем.

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

Основные преимущества использования LinkedList возникают при повторном использовании существующих итераторов для вставки и удаления элементов. Затем эти операции можно выполнить в O (1) путем изменения только локального списка. В списке массивов остальная часть массива должна быть перемещена (т.е. скопирована). С другой стороны, поиск в LinkedList означает следующие ссылки в O (n) (n/2 шага) для наихудшего случая, тогда как в ArrayList желаемая позиция может быть математически вычислена и доступна в O (1).

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

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

Начальная емкость ArrayList умолчанию довольно маленькая (10 из Java 1.4 - 1.8). Но поскольку базовая реализация представляет собой массив, массив должен быть изменен, если вы добавите много элементов. Чтобы избежать высокой стоимости изменения размера, когда вы знаете, что собираетесь добавить много элементов, ArrayList с более высокой начальной емкостью.

  • 158
    Забыл упомянуть стоимость вставки. В LinkedList, когда у вас есть правильная позиция, вставка стоит O (1), тогда как в ArrayList она достигает O (n) - все элементы после точки вставки должны быть перемещены.
  • 22
    Что касается использования Vector: на самом деле нет необходимости возвращаться к Vector. Способ сделать это с вашей предпочтительной реализацией List и вызовом synchronizedList, чтобы получить синхронизированную оболочку. Смотрите: java.sun.com/docs/books/tutorial/collections/implementations/…
Показать ещё 37 комментариев
529

До сих пор, похоже, никто не обращал внимания на объем памяти каждого из этих списков, кроме общего мнения, что LinkedList "намного больше", чем ArrayList поэтому я немного разбирал числа, чтобы продемонстрировать, насколько точно оба списка занимают N пустых ссылок,

Поскольку в их относительных системах ссылки бывают 32- или 64-битными (даже если они равны нулю), я включил 4 набора данных для 32- и 64-битных LinkedLists и ArrayLists.

Примечание. Размеры, показанные для строк ArrayList предназначены для усеченных списков. На практике емкость резервного массива в ArrayList обычно больше, чем его текущее количество элементов.

Примечание 2: (спасибо BeeOnRope) Поскольку CompressedOops теперь используется по умолчанию начиная с середины JDK6 и выше, приведенные ниже значения для 64-разрядных компьютеров будут в основном соответствовать их 32-разрядным аналогам, если, конечно, вы специально не отключите его.


Изображение 1310


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

Формулы, которые я использовал, следуют, дайте мне знать, если я сделал что-то не так, и я исправлю это. "b" - это 4 или 8 для 32- или 64-разрядных систем, а "n" - количество элементов. Обратите внимание, что причина для модов в том, что все объекты в java будут занимать кратное 8 байт пространство независимо от того, все они используются или нет.

ArrayList:

ArrayList object header + size integer + modCount integer + array reference + (array oject header + b * n) + MOD(array oject, 8) + MOD(ArrayList object, 8) == 8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8) + MOD(8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8), 8)

LinkedList:

LinkedList object header + size integer + modCount integer + reference to header + reference to footer + (node object overhead + reference to previous element + reference to next element + reference to element) * n) + MOD(node object, 8) * n + MOD(LinkedList object, 8) == 8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n + MOD(8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n, 8)

  • 1
    Довольно интересно видеть, что LinkedList требует столько же памяти, сколько и ArrayList для хранения одного элемента. Как не интуитивно понятно! Что произойдет, если вы запустите свой пример с -XX: + UseCompressedOops?
  • 177
    Проблема с вашей математикой в том, что ваш график сильно преувеличивает влияние. Вы моделируете объекты, каждый из которых содержит только int , то есть 4 или 8 байтов данных. В связанном списке есть, по сути, 4 «слова» накладных расходов. Таким образом, ваш график создает впечатление, что связанные списки используют «пять раз» хранилище списков массивов. Это не верно. Накладные расходы составляют 16 или 32 байта на объект, как аддитивная корректировка, а не коэффициент масштабирования.
Показать ещё 7 комментариев
208

ArrayList - это то, что вы хотите. LinkedList почти всегда является ошибкой (производительности).

Почему LinkedList отстой:

  • Он использует множество небольших объектов памяти и, следовательно, влияет на производительность в процессе.
  • Множество мелких объектов плохо для локализации кэша.
  • Любая индексированная операция требует обхода, то есть имеет O (n) производительность. Это не очевидно в исходном коде, что приводит к алгоритмам O (n) медленнее, чем при использовании ArrayList.
  • Получение хорошей производительности сложно.
  • Даже когда производительность большого вывода совпадает с ArrayList, в любом случае, вероятно, она будет значительно медленнее.
  • Это раздражает, чтобы видеть LinkedList в источнике, потому что это, вероятно, неправильный выбор.
  • 208
    Сожалею. отметил вас вниз LinkedList не сосет. Существуют ситуации, когда LinkedList является правильным классом для использования. Я согласен, что не так много ситуаций, когда это лучше, чем arraylist, но они существуют. Обучайте людей, которые делают глупости!
  • 37
    Жаль видеть, что вы получили много отрицательных голосов за это. Существует действительно очень мало причин для использования Java LinkedList. В дополнение к плохой производительности он также использует намного больше памяти, чем другие конкретные классы List (каждый узел имеет два дополнительных указателя, и каждый узел представляет собой отдельный объект-обертку с дополнительными байтами служебной информации, которые идут вместе с ними).
Показать ещё 27 комментариев
136

Как человек, занимающийся разработкой оперативной производительности на очень крупных веб-сервисах SOA в течение примерно десятилетия, я бы предпочел поведение LinkedList над ArrayList. Хотя стационарная пропускная способность LinkedList хуже и, следовательно, может привести к покупке большего количества аппаратных средств - поведение ArrayList под давлением может привести к тому, что приложения в кластере будут расширять свои массивы почти синхронно, а большие размеры массивов могут привести к отсутствию реакции в приложении и отключении, находясь под давлением, что является катастрофическим поведением.

Аналогично, вы можете получить более высокую пропускную способность в приложении из сборщика мусора, используемого по умолчанию, но как только вы получите java-приложения с кучей 10 ГБ, вы можете завершить блокировку приложения на 25 секунд во время полного GC, что вызывает таймауты и сбои в приложениях SOA и удаляет ваши SLA, если это происходит слишком часто. Несмотря на то, что сборщик CMS потребляет больше ресурсов и не достигает такой же сырой пропускной способности, это гораздо лучший выбор, поскольку он имеет более предсказуемую и меньшую задержку.

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

  • 8
    Разве другое решение не будет управлять размером списка программным способом, используя метод ArrayList sureCapacity ()? Мой вопрос: почему так много вещей хранится в куче хрупких структур данных, когда их лучше хранить в механизме кэширования или БД? На днях у меня было интервью, где они ругались вверх и вниз по поводу зла ArrayList, но я прихожу сюда и обнаруживаю, что анализ сложности намного лучше! БОЛЬШАЯ ТОЧКА ДЛЯ ОБСУЖДЕНИЯ, ХОТЯ. СПАСИБО!
  • 18
    как только вы получаете java-приложения с кучей 10 ГБ, вы можете заблокировать приложение на 25 секунд во время полного GC, что приводит к тайм-аутам. На самом деле с LinkedList вы убиваете сборщик мусора во время полного GC, ему приходится повторять слишком большой LinkedList с пропуском кеша каждый узел.
Показать ещё 8 комментариев
112
Algorithm           ArrayList   LinkedList
seek front            O(1)         O(1)
seek back             O(1)         O(1)
seek to index         O(1)         O(N)
insert at front       O(N)         O(1)
insert at back        O(1)         O(1)
insert after an item  O(N)         O(1)

Алгоритмы: Big-Oh Notation

ArrayLists хороши для write-once-read-many или appenders, но плохо при добавлении/удалении спереди или в середине.

  • 36
    Вы не можете сравнивать значения Big-O напрямую, не думая о постоянных факторах. Для небольших списков (а большинство списков маленькие) O (N) ArrayList быстрее, чем O (1) LinkedList.
  • 3
    Меня не волнует производительность небольших списков, и мой компьютер тоже не заботится, если он не используется каким-либо образом в цикле.
Показать ещё 9 комментариев
92

Да, я знаю, это древний вопрос, но я брошу свои два цента:

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

Существует один общий вариант использования, в котором LinkedList превосходит ArrayList: очередь. Однако, если ваша цель - производительность, вместо LinkedList вы также должны рассмотреть возможность использования ArrayBlockingQueue (если вы можете заранее определить верхнюю границу вашего размера очереди и можете позволить себе выделить всю память вверх), или это реализация CircularArrayList. (Да, это с 2001 года, так что вам нужно будет его обобщить, но я получил сопоставимые показатели производительности с тем, что цитируется в статье только в недавней JVM)

  • 37
    С Java 6 вы можете использовать ArrayDeque . docs.oracle.com/javase/6/docs/api/java/util/ArrayDeque.html
  • 1
    ArrayDeque медленнее, чем LinkedList если все операции не выполняются с одного конца. Это нормально, когда используется в качестве стека, но это не делает хорошую очередь.
Показать ещё 4 комментария
53

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

Array vs ArrayList vs LinkedList vs Vector идет более подробно, как и Linked List.

50

Правильно или неверно: Пожалуйста, выполните тест на месте и решите сами!

Изменить/Удалить быстрее в LinkedList чем в ArrayList.

ArrayList, поддерживаемый Array, который должен быть в два раза больше, хуже в приложении большого объема.

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


Operation                       ArrayList                      LinkedList  

AddAll   (Insert)               101,16719                      2623,29291 

Add      (Insert-Sequentially)  152,46840                      966,62216

Add      (insert-randomly)      36527                          29193

remove   (Delete)               20,56,9095                     20,45,4904

contains (Search)               186,15,704                     189,64,981

Здесь код:

import org.junit.Assert;
import org.junit.Test;

import java.util.*;

public class ArrayListVsLinkedList {
    private static final int MAX = 500000;
    String[] strings = maxArray();

    ////////////// ADD ALL ////////////////////////////////////////
    @Test
    public void arrayListAddAll() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        watch.start();
        arrayList.addAll(stringList);
        watch.totalTime("Array List addAll() = ");//101,16719 Nanoseconds
    }

    @Test
    public void linkedListAddAll() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);

        watch.start();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(stringList);
        watch.totalTime("Linked List addAll() = ");  //2623,29291 Nanoseconds
    }

    //Note: ArrayList is 26 time faster here than LinkedList for addAll()

    ///////////////// INSERT /////////////////////////////////////////////
    @Test
    public void arrayListAdd() {
        Watch watch = new Watch();
        List<String> arrayList = new ArrayList<String>(MAX);

        watch.start();
        for (String string : strings)
            arrayList.add(string);
        watch.totalTime("Array List add() = ");//152,46840 Nanoseconds
    }

    @Test
    public void linkedListAdd() {
        Watch watch = new Watch();

        List<String> linkedList = new LinkedList<String>();
        watch.start();
        for (String string : strings)
            linkedList.add(string);
        watch.totalTime("Linked List add() = ");  //966,62216 Nanoseconds
    }

    //Note: ArrayList is 9 times faster than LinkedList for add sequentially

    /////////////////// INSERT IN BETWEEN ///////////////////////////////////////

    @Test
    public void arrayListInsertOne() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX + MAX / 10);
        arrayList.addAll(stringList);

        String insertString0 = getString(true, MAX / 2 + 10);
        String insertString1 = getString(true, MAX / 2 + 20);
        String insertString2 = getString(true, MAX / 2 + 30);
        String insertString3 = getString(true, MAX / 2 + 40);

        watch.start();

        arrayList.add(insertString0);
        arrayList.add(insertString1);
        arrayList.add(insertString2);
        arrayList.add(insertString3);

        watch.totalTime("Array List add() = ");//36527
    }

    @Test
    public void linkedListInsertOne() {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(stringList);

        String insertString0 = getString(true, MAX / 2 + 10);
        String insertString1 = getString(true, MAX / 2 + 20);
        String insertString2 = getString(true, MAX / 2 + 30);
        String insertString3 = getString(true, MAX / 2 + 40);

        watch.start();

        linkedList.add(insertString0);
        linkedList.add(insertString1);
        linkedList.add(insertString2);
        linkedList.add(insertString3);

        watch.totalTime("Linked List add = ");//29193
    }


    //Note: LinkedList is 3000 nanosecond faster than ArrayList for insert randomly.

    ////////////////// DELETE //////////////////////////////////////////////////////
    @Test
    public void arrayListRemove() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        arrayList.addAll(stringList);
        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        arrayList.remove(searchString0);
        arrayList.remove(searchString1);
        watch.totalTime("Array List remove() = ");//20,56,9095 Nanoseconds
    }

    @Test
    public void linkedListRemove() throws Exception {
        Watch watch = new Watch();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(Arrays.asList(strings));

        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        linkedList.remove(searchString0);
        linkedList.remove(searchString1);
        watch.totalTime("Linked List remove = ");//20,45,4904 Nanoseconds
    }

    //Note: LinkedList is 10 millisecond faster than ArrayList while removing item.

    ///////////////////// SEARCH ///////////////////////////////////////////
    @Test
    public void arrayListSearch() throws Exception {
        Watch watch = new Watch();
        List<String> stringList = Arrays.asList(strings);
        List<String> arrayList = new ArrayList<String>(MAX);

        arrayList.addAll(stringList);
        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        arrayList.contains(searchString0);
        arrayList.contains(searchString1);
        watch.totalTime("Array List addAll() time = ");//186,15,704
    }

    @Test
    public void linkedListSearch() throws Exception {
        Watch watch = new Watch();
        List<String> linkedList = new LinkedList<String>();
        linkedList.addAll(Arrays.asList(strings));

        String searchString0 = getString(true, MAX / 2 + 10);
        String searchString1 = getString(true, MAX / 2 + 20);

        watch.start();
        linkedList.contains(searchString0);
        linkedList.contains(searchString1);
        watch.totalTime("Linked List addAll() time = ");//189,64,981
    }

    //Note: Linked List is 500 Milliseconds faster than ArrayList

    class Watch {
        private long startTime;
        private long endTime;

        public void start() {
            startTime = System.nanoTime();
        }

        private void stop() {
            endTime = System.nanoTime();
        }

        public void totalTime(String s) {
            stop();
            System.out.println(s + (endTime - startTime));
        }
    }


    private String[] maxArray() {
        String[] strings = new String[MAX];
        Boolean result = Boolean.TRUE;
        for (int i = 0; i < MAX; i++) {
            strings[i] = getString(result, i);
            result = !result;
        }
        return strings;
    }

    private String getString(Boolean result, int i) {
        return String.valueOf(result) + i + String.valueOf(!result);
    }
}
  • 1
    ArrayList не должен быть удвоен, если быть точным. Пожалуйста, проверьте источники в первую очередь.
  • 0
    Следует отметить, что ваш пример имеет недостатки ... Вы удаляете из строки размером: 18 + [2, 12] байтов ("true0false", "true500000false"), в среднем 25 байтов, которые являются размерами элементов в середине. Известно, что при увеличении размера байта элемента связанный список работает лучше, а при увеличении размера списка непрерывный массив (список) будет работать лучше. Самое главное, вы делаете .equals () для строк - это не дешевая операция. Если бы вы вместо этого использовали целые числа, я думаю, что будет разница.
Показать ещё 6 комментариев
42

ArrayList по существу является массивом. LinkedList реализуется как двойной связанный список.

get довольно ясно. O (1) для ArrayList, поскольку ArrayList допускает произвольный доступ с использованием индекса. O (n) для LinkedList, потому что он должен сначала найти индекс. Примечание. Существуют разные версии add и remove.

LinkedList быстрее добавляет и удаляет, но медленнее получается. Вкратце, LinkedList должен быть предпочтительнее, если:

  1. нет большого количества случайного доступа элемента
  2. существует большое количество операций добавления/удаления

=== ArrayList ===

  • add (E e)
    • добавить в конец ArrayList
    • требуют изменения размера памяти.
    • O (n) хуже, O (1) амортизируется
  • add (индекс int, элемент E)
    • добавить к определенной позиции индекса
    • требуют смещения и возможной стоимости изменения размера памяти
    • На)
  • remove (int index)
    • удалить указанный элемент
    • требуют смещения и возможной стоимости изменения размера памяти
    • На)
  • remove (Object o)
    • удалить первое вхождение указанного элемента из этого списка
    • необходимо сначала выполнить поиск по элементу, а затем сдвинуть и возможную стоимость изменения размера памяти
    • На)

=== LinkedList ===

  • add (E e)

    • добавить в конец списка
    • O (1)
  • add (индекс int, элемент E)

    • вставить в указанное положение
    • нужно сначала найти позицию
    • На)
  • Удалить()
    • удалить первый элемент списка
    • O (1)
  • remove (int index)
    • удалить элемент с указанным индексом
    • нужно сначала найти элемент
    • На)
  • remove (Object o)
    • удалить первое вхождение указанного элемента
    • нужно сначала найти элемент
    • На)

Вот цифра от programcreek.com (add и remove - это первый тип, т.е. Добавление элемента в конце списка и удаление элемента в указанной позиции в списке.):

Изображение 1311

  • 3
    Msgstr "LinkedList быстрее, чем добавить / удалить". Неправильно, проверьте ответ выше stackoverflow.com/a/7507740/638670
31

Джошуа Блох, автор LinkedList:

Кто-нибудь действительно использует LinkedList? Я написал это, и я никогда не использую его.

Ссылка: https://twitter.com/joshbloch/status/583813919019573248

Мне жаль, что ответ был не таким информативным, как другие ответы, но я подумал, что это будет самым интересным и понятным.

  • 2
    Я пришел в эту ветку исключительно для того, чтобы проверить, упоминается ли твит Джошуа. Это :)
31

1) Поиск: операция поиска ArrayList довольно быстро по сравнению с операцией поиска LinkedList. get (int index) в ArrayList дает производительность O (1), а производительность LinkedList - O (n).

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

2) Удаление: операция удаления LinkedList дает O (1) производительность, в то время как ArrayList дает переменную производительность: O (n) в худшем случае (при удалении первого элемента) и O (1) в лучшем случае (при удалении последнего элемента),

Вывод: удаление элемента LinkedList происходит быстрее по сравнению с ArrayList.

Причина. Каждый элемент LinkedLists поддерживает два указателя (адреса), которые указывают на оба соседних элемента в списке. Следовательно, удаление требует только изменения местоположения указателя в двух соседних узлах (элементах) узла, который будет удален. В то время как в ArrayList все элементы необходимо сдвинуть, чтобы заполнить пространство, созданное удаленным элементом.

3) Вставка производительности: метод добавления LinkedList дает O (1) производительность, в то время как ArrayList дает O (n) в худшем случае. Причина та же, что и для удаления.

4) Накладные расходы памяти: ArrayList поддерживает индексы и данные элемента, а LinkedList поддерживает данные элемента и два указателя для соседних узлов, следовательно, потребление памяти в LinkedList сравнительно велико.

Существует несколько сходств между этими классами, которые заключаются в следующем:

И ArrayList, и LinkedList - это реализация интерфейса List. Они оба поддерживают порядок вставки элементов, что означает, что при отображении элементов ArrayList и LinkedList набор результатов будет иметь тот же порядок, в котором элементы были вставлены в список. Оба эти класса не синхронизированы и могут быть синхронизированы явно с помощью метода Collections.synchronizedList. Итератор и listIterator, возвращаемые этими классами, являются неудачными (если список структурно изменен в любое время после создания итератора, любым способом, кроме как через собственные методы удаления или добавления итераторов, итератор будет вызывать исключение ConcurrentModificationException).

Когда использовать LinkedList и когда использовать ArrayList?

1) Как объяснялось выше, операции вставки и удаления дают хорошую производительность (O (1)) в LinkedList по сравнению с ArrayList (O (n)). Следовательно, если в приложении есть требование частого добавления и удаления, тогда LinkedList является лучшим выбором.

2) Операции поиска (get method) бывают быстрыми в ArrayList (O (1)), но не в LinkedList (O (n)), поэтому, если есть меньше операций добавления и удаления и большего количества операций поиска, ArrayList будет вашим лучшим выбором.

  • 2
    Я не согласен с пунктами 2 и 3. LinkedList по-прежнему придется перемещаться в правильную позицию для вставки / удаления узла и, следовательно, будет иметь сложность O (n), если ему не нужно вставлять / удалять в начале / конце списка.
  • 0
    в основном, используйте связанный список для списков спрайтов в играх, которые вам нужно пройти через все в любом случае и удалить или вставить при прохождении. однако для этого нужно написать лучший связанный список для этого конкретного использования, поскольку LinkedList в java действует как академический пример.
Показать ещё 1 комментарий
31

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

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

  • 14
    LinkedList не дешев для добавления элементов. Почти всегда быстрее добавить миллион элементов в ArrayList, чем добавить их в LinkedList. И большинство списков в реальном коде не содержат даже миллиона элементов.
  • 9
    В любой момент вы знаете стоимость добавления элемента в свой LinkedList. ArrayList у вас нет (в общем). Добавление одного элемента в ArrayList, содержащий миллион элементов, может занять очень много времени - это операция O (n) плюс двойное хранилище, если только вы не распределили пространство. Добавление элемента в LinkedList - это O (1). Мое последнее утверждение остается в силе.
Показать ещё 6 комментариев
19

Я знаю, что это старый пост, но я честно не могу поверить, что никто не упоминал, что LinkedList реализует Deque. Просто посмотрите на методы в DequeQueue); если вы хотите провести честное сравнение, попробуйте запустить LinkedList против ArrayDeque и выполнить сравнение функций для функций.

18

Если ваш код add(0) и remove(0), используйте LinkedList и addFirst() removeFirst() методы addFirst() и removeFirst(). В противном случае используйте ArrayList.

И, конечно же, Guava ImmutableList - ваш лучший друг.

  • 3
    Для небольших списков ArrayList.add (0) всегда будет работать быстрее, чем LinkedList.addFirst ().
  • 1
    -1. ArrayDeque лучше для этого случая.
Показать ещё 2 комментария
16

Вот запись Big-O как в ArrayList и в LinkedList а также в CopyOnWrite-ArrayList:

ArrayList

get                 O(1)
add                 O(1)
contains            O(n)
next                O(1)
remove              O(n)
iterator.remove     O(n)

LinkedList

get                 O(n)
add                 O(1)
contains            O(n)
next                O(1)
remove              O(1)
iterator.remove     O(1)

CopyOnWrite-ArrayList

get                 O(1)
add                 O(n)
contains            O(n)
next                O(1)
remove              O(n)
iterator.remove     O(n)

Исходя из этого, вы должны решить, что выбрать. :)

  • 6
    >>>> ArrayList add -> O (1) <- не правда. В некоторых случаях ArrayList должен будет расти, чтобы добавить еще один элемент
  • 0
    Удаление LinkedList - это не O (1), для этого потребуется поиск удаляемого элемента, поэтому наихудший O (n) и средний O (n / 2)
12

Давайте сравним LinkedList и ArrayList с параметрами:

1. Реализация

ArrayList - это переменная реализация массива списка, в то время как

LinkedList - это реализация списка ссылок с двойным соединением.


2. Производительность

  • get (индекс int) или операция поиска

    Операция getArrayList get (int index) выполняется в постоянное время, то есть O (1) while

    Время выполнения операции LinkedList get (int index) равно O (n).

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

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

  • insert() или добавить (Object)

    Вставки в LinkedList обычно бывают быстрыми, как сравнение с ArrayList. В добавлении или вставке LinkedList выполняется операция O (1).

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

  • remove (int)

    Удалить операцию в LinkedList, как правило, совпадает с ArrayList, то есть O (n).

    В LinkedList существует два перегруженных метода удаления. один - remove() без какого-либо параметра, который удаляет головку списка и запускается в постоянное время O (1). Другим перегруженным методом удаления в LinkedList является remove (int) или remove (Object), который удаляет Object или int, переданные в качестве параметра. Этот метод пересекает LinkedList, пока не найдет объект и не отделит его от исходного списка. Следовательно, это время выполнения метода O (n).

    Хотя метод ArrayList remove (int) включает в себя копирование элементов из старого массива в новый обновленный массив, отсюда его время выполнения - O (n).


3. Обратный итератор

LinkedList можно повторить в обратном направлении, используя descendingIterator(), в то время как

в ArrayList отсутствует descendingIterator(), поэтому нам нужно написать собственный код для повторения по ArrayList в обратном направлении.


4. Начальная мощность

Если конструктор не перегружен, то ArrayList создает пустой список начальной емкости 10, тогда как

LinkedList только создает пустой список без какой-либо начальной емкости.


5. Накладные расходы памяти

Накладные расходы памяти в LinkedList больше по сравнению с ArrayList, поскольку узел в LinkedList должен поддерживать адреса следующего и предыдущего узлов. В то время как

В ArrayList каждый индекс содержит только фактический объект (данные).


Источник

11

Здесь важно различать как

 Array List is better for storing and accessing data.

Linked List is better for manipulating data.
11

Посмотрите на изображение ниже.

http://javaconceptoftheday.com/wp-content/uploads/2014/12/ArrayListVsLinkedList.png

Источник изображения: ArrayList Vs LinkedList В Java.

11

В дополнение к другим хорошим аргументам выше, вы должны заметить, что ArrayList реализует интерфейс RandomAccess, а LinkedList реализует Queue.

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

8
  • 1
    Привет @chharvey, ссылка только ответы получить 6 Upvotes? Пожалуйста, добавьте несколько пунктов, которые могут поддержать ссылку. Что если oracle изменит свою ссылку?
7

Список массивов по существу представляет собой массив с методами для добавления элементов и т.д. (и вместо этого вы должны использовать общий список). Это набор элементов, к которым можно получить доступ с помощью индексатора (например, [0]). Это подразумевает переход от одного пункта к другому.

Связанный список указывает переход от одного элемента к другому (Item a → item b). Вы можете получить тот же эффект с помощью списка массивов, но связанный список абсолютно говорит, какой элемент должен следовать предыдущему.

7

Это зависит от того, какие операции вы будете делать больше в Списке.

ArrayList быстрее получает доступ к индексированному значению. Это намного хуже при вставке или удалении объектов.

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

  • 2
    Чтобы узнать больше, не читайте, просто напишите код. и вы обнаружите, что реализация ArrayList быстрее, чем LinkedList при вставке и удалении.
6

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


Теоретически, LinkedList имеет O (1) для add(E element)

Также добавление элемента в середине списка должно быть очень эффективным.

Практика совсем иная, так как LinkedList - это структура данных Cache Hostile Data. От производительности POV - очень мало случаев, когда LinkedList мог бы работать лучше, чем дружественный к ArrayList.

Вот результаты тестового тестирования вставки элементов в случайных местах. Как видите, список массивов гораздо эффективнее, хотя теоретически каждая вставка в середине списка потребует "переместить" n более поздних элементов массива (чем меньше значение, тем лучше):

Изображение 1312

Работа на оборудовании более позднего поколения (большие, более эффективные кэши) - результаты еще более убедительны:

Изображение 1313

LinkedList требует гораздо больше времени для выполнения той же работы. Источник Исходный код

Для этого есть две основные причины:

  1. Главным образом - то, что узлы LinkedList случайно разбросаны по памяти. ОЗУ ("Память с произвольным доступом") на самом деле не является случайным, и блоки памяти должны быть извлечены для кэширования. Эта операция занимает много времени, и когда такие выборки происходят часто - страницы памяти в кеше необходимо постоянно заменять → Cache misses → Cache неэффективен. Элементы ArrayList хранятся в непрерывной памяти - именно для этого оптимизируется современная архитектура ЦП.

  2. Вторичный LinkedList требуется для удержания указателей назад/вперед, что означает 3-х кратное потребление памяти на хранимое значение по сравнению с ArrayList.

DynamicIntArray, кстати, является пользовательской реализацией ArrayList, содержащей Int (примитивный тип), а не Objects - следовательно, все данные действительно хранятся смежно - следовательно, еще более эффективно.

Ключевым элементом, который следует помнить, является то, что стоимость выборки блока памяти является более значительной, чем стоимость доступа к одной ячейке памяти. Вот почему считыватель 1 МБ последовательной памяти работает в х400 раз быстрее, чем считывает этот объем данных из разных блоков памяти:

Latency Comparison Numbers (~2012)
----------------------------------
L1 cache reference                           0.5 ns
Branch mispredict                            5   ns
L2 cache reference                           7   ns                      14x L1 cache
Mutex lock/unlock                           25   ns
Main memory reference                      100   ns                      20x L2 cache, 200x L1 cache
Compress 1K bytes with Zippy             3,000   ns        3 us
Send 1K bytes over 1 Gbps network       10,000   ns       10 us
Read 4K randomly from SSD*             150,000   ns      150 us          ~1GB/sec SSD
Read 1 MB sequentially from memory     250,000   ns      250 us
Round trip within same datacenter      500,000   ns      500 us
Read 1 MB sequentially from SSD*     1,000,000   ns    1,000 us    1 ms  ~1GB/sec SSD, 4X memory
Disk seek                           10,000,000   ns   10,000 us   10 ms  20x datacenter roundtrip
Read 1 MB sequentially from disk    20,000,000   ns   20,000 us   20 ms  80x memory, 20X SSD
Send packet CA->Netherlands->CA    150,000,000   ns  150,000 us  150 ms

Источник: число задержек, которое должен знать каждый программист

Просто чтобы сделать это еще более ясным, пожалуйста, проверьте эталон добавления элементов в начало списка. Это случай использования, в котором, по идее, LinkedList должен действительно сиять, а ArrayList должен представлять плохие или даже худшие результаты:

Изображение 1314

Примечание: это эталон библиотеки C++ Std, но мой предыдущий опыт показал, что результаты C++ и Java очень похожи. Исходный код

Копирование последовательного объема памяти - это операция, оптимизированная современными процессорами. Она меняет теорию и фактически делает ArrayList/Vector намного более эффективной.


Кредиты: Все опубликованные тесты созданы Kjell Hedström. Еще больше данных можно найти в его блоге

  • 0
    Я бы не назвал очередь уникальной или экстремальной! Очередь fifo гораздо проще реализовать в LinkedList, а не в ArrayList. Это на самом деле кошмар для ArrayList, так как вы должны отслеживать свой собственный запуск, остановку и перераспределение, вы можете использовать массив, но Linked List - это fifo. Я не уверен насчет реализации Java, но LinkedList может выполнять O (1) для операций как очереди, так и удаления очереди (Требуется специальный указатель на элемент tail для удаления, который, как я предполагаю, есть в java, но я не проверял дважды .)
6

Операция get (i) в ArrayList быстрее, чем LinkedList, потому что:
ArrayList: Реализуемая реализация интерфейса списка с разрешением resizeable LinkedList: Реализованная в двойном списке реализация интерфейсов List и Deque

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

6

Я прочитал ответы, но есть один сценарий, где я всегда использую LinkedList над ArrayList, который я хочу поделиться, чтобы услышать мнения:

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

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

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

6

Важная особенность связанного списка (который я не читал в другом ответе) - это объединение двух списков. С массивом это O (n) (+ накладные расходы некоторых перераспределений) со связанным списком, это только O (1) или O (2); -)

Важно. Для Java LinkedList это неверно! См. Есть ли быстрый метод concat для связанного списка в Java?

  • 2
    Как так? Это может быть верно для структур данных связанного списка, но не для объекта Java LinkList. Вы не можете просто указать next из одного списка на первый узел во втором списке. Единственный способ - это использовать addAll() который добавляет элементы последовательно, хотя это лучше, чем циклически вызывать и вызывать add() для каждого элемента. Чтобы сделать это быстро в O (1), вам понадобится класс композитинга (например, org.apache.commons.collections.collection.CompositeCollection), но тогда это будет работать для любого вида List / Collection.
  • 0
    Да, верно. Я отредактировал ответ соответственно. но посмотрите ответ на вопрос «как» сделать это с LinkedList: stackoverflow.com/questions/2494031/…
5

ArrayList и LinkedList имеют свои плюсы и минусы.

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

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

Если в вашем приложении часто используются операции поиска, используйте ArrayList. Если у вас есть частая вставка и удаление, используйте LinkedList.

5

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

ArrayList Vs LinkedList

1) Search: ArrayList операция поиска довольно быстро по сравнению с операцией поиска LinkedList. get(int index) в ArrayList дает производительность O(1), тогда как LinkedList производительность O(n).

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

2) Deletion: LinkedList операция удаления дает O(1) производительность, а ArrayList дает переменную производительность: O(n) в худшем случае (при удалении первого элемента) и O(1) в лучшем случае (при удалении последнего элемента).

Вывод: удаление элемента LinkedList происходит быстрее по сравнению с ArrayList.

Причина: LinkedLists Каждый элемент поддерживает два указателя (адреса), который указывает на оба соседних элемента в списке. Следовательно, для удаления требуется только изменение местоположения указателя в двух соседних узлах (элементах) node, которые будут удалены. В то время как в ArrayList все элементы необходимо сдвинуть, чтобы заполнить пространство, созданное удаленным элементом.

3) Inserts Performance: LinkedList метод добавления дает O(1) производительность, а ArrayList дает O(n) в худшем случае. Причина та же, что и для удаления.

4) Memory Overhead: ArrayList поддерживает индексы и данные элемента, а LinkedList поддерживает данные элемента и два указателя для соседних узлов

следовательно, потребление памяти в LinkedList сравнительно велико.

Существует несколько сходств между этими классами:

  • Оба ArrayList и LinkedList - это реализация интерфейса List.
  • Оба они поддерживают порядок вставки элементов, что означает, что при отображении элементов ArrayList и LinkedList набор результатов будет иметь тот же порядок, в котором элементы были вставлены в список.
  • Оба этих класса не синхронизированы и могут быть синхронизированы явно с помощью метода Collections.synchronizedList.
  • iterator и listIterator, возвращаемые этими классами, являются fail-fast (если список структурно изменен в любое время после создания итератора, любым способом, кроме как с помощью методов удаления или добавления iterator’s, итератор будет throw a ConcurrentModificationException).

Когда использовать LinkedList и когда использовать ArrayList?

  • Как объяснялось выше, операции вставки и удаления дают хорошую производительность (O(1)) в LinkedList по сравнению с ArrayList(O(n)).

    Следовательно, если в приложении есть требование частого добавления и удаления, тогда LinkedList - лучший выбор.

  • Операции поиска (get method) выполняются быстро в Arraylist (O(1)), но не в LinkedList (O(n))

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

2

1) Базовая структура данных

Первое различие между ArrayList и LinkedList связано с тем, что ArrayList поддерживается Array, а LinkedList поддерживается LinkedList. Это приведет к дальнейшим различиям в производительности.

2) LinkedList реализует Deque

Другое отличие между ArrayList и LinkedList заключается в том, что помимо интерфейса List LinkedList также реализует интерфейс Deque, который обеспечивает первую в первых операциях функции add() и poll() и несколько других функций Deque. 3) Добавление элементов в ArrayList. Добавление элемента в ArrayList - это операция O (1), если она не вызывает повторный размер массива, в этом случае она становится O (log (n)). С другой стороны, добавление элемента в LinkedList - это операция O (1), так как она не требует навигации.

4) Удаление элемента из положения

Чтобы удалить элемент из определенного индекса, например, вызвав remove (index), ArrayList выполняет операцию копирования, которая делает ее близкой к O (n), в то время как LinkedList должен пройти к этой точке, что также делает ее O (n/2), так как он может проходить с любого направления, основанного на близости.

5) Итерация по ArrayList или LinkedList

Итерация - это операция O (n) для LinkedList и ArrayList, где n - число элементов.

6) Извлечение элемента из положения

Операция get (index) - это O (1) в ArrayList, а O (n/2) в LinkedList, поскольку она должна проходить до этой записи. Хотя в записи Big O O (n/2) есть только O (n), потому что мы игнорируем там константы.

7) Память

LinkedList использует объект-оболочку, Entry, который является статическим вложенным классом для хранения данных и двух узлов next и previous, в то время как ArrayList просто хранит данные в массиве.

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

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

Из всех вышеперечисленных различий между ArrayList и LinkedList, похоже, что ArrayList является лучшим выбором, чем LinkedList почти во всех случаях, за исключением случаев, когда вы выполняете частое действие add(), чем remove() или get().

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

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

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

  • 0
    Я думаю, что это лучший заявленный ответ всей группы здесь. Это точно и информативно. Я бы предложил изменить последнюю строку - в конце добавить «помимо очередей», которые являются очень важными структурами, которые действительно не имеют смысла для связанного списка вообще.
1

И remove(), и insert() имеют эффективность выполнения O (n) как для ArrayLists, так и для LinkedLists. Однако причина линейного времени обработки объясняется двумя разными причинами:

В ArrayList вы попадаете в элемент в O (1), но на самом деле удаление или вставка чего-то делает его O (n), потому что все следующие элементы необходимо изменить.

В LinkedList для фактического перехода к желаемому элементу требуется O (n), потому что мы должны начинать с самого начала, пока не достигнем желаемого индекса. Фактически удаление или вставка является постоянным, потому что нам нужно только изменить 1 ссылку для remove() и 2 ссылки для insert().

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

Бонус: Хотя нет способа сделать эти два метода O (1) для ArrayList, на самом деле есть способ сделать это в LinkedLists. Скажем, мы хотим пройти весь список, удалив и вставив элементы на нашем пути. Обычно вы начинаете с самого начала для каждого элемента с помощью LinkedList, мы также можем "сохранить" текущий элемент, с которым мы работаем с Iterator. С помощью Iterator мы получаем эффективность O (1) для remove() и insert() при работе в LinkedList. Являясь единственным преимуществом производительности, я знаю, где LinkedList всегда лучше, чем ArrayList.

0

Один из тестов, которые я видел здесь, проводит только один раз. Но я заметил, что вам нужно много раз запускать эти тесты, и в конечном итоге их время будет сходиться. В принципе, JVM нужно прогревать. Для моего конкретного случая использования мне нужно было добавлять/удалять элементы до последнего, которые вырастают примерно до 500 элементов. В моих тестах LinkedList вышел быстрее, а связанный LinkedList приблизился к 50 000 NS и ArrayList приходящих примерно в 90 000 NS... дайте или возьмите. См. Код ниже.

public static void main(String[] args) {
    List<Long> times = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        times.add(doIt());
    }
    System.out.println("avg = " + (times.stream().mapToLong(x -> x).average()));
}

static long doIt() {
    long start = System.nanoTime();
    List<Object> list = new LinkedList<>();
    //uncomment line below to test with ArrayList
    //list = new ArrayList<>();
    for (int i = 0; i < 500; i++) {
        list.add(i);
    }

    Iterator it = list.iterator();
    while (it.hasNext()) {
        it.next();
        it.remove();
    }
    long end = System.nanoTime();
    long diff = end - start;
    //uncomment to see the JVM warmup and get faster for the first few iterations
    //System.out.println(diff)
    return diff;
}
0

ArrayList расширяет AbstractList и реализует интерфейс List. ArrayList - это динамический массив.
Можно сказать, что он был в основном создан для преодоления недостатков массивов

Класс LinkedList расширяет AbstractSequentialList и реализует интерфейс List, Deque и Queue.
Производительность
arraylist.get() - O (1), тогда как linkedlist.get() - O (n)
arraylist.add() - O (1) и linkedlist.add() равно 0 (1)
arraylist.contains() - O (n) и linkedlist.contains() равно O (n)
arraylist.next() - O (1), а linkedlist.next() - O (1)
arraylist.remove() - O (n), тогда как linkedlist.remove() - O (1)
В arraylist
iterator.remove() - O (n), в то время как In linkedlist - iterator.remove() - O (1)

0

Если вы хотите добавить элемент или удалить элемент из списка, не беспокоясь о местоположении объекта, используйте ArrayList. Это будет быстрее, чем связанный список. Предположим, если вы хотите добавить или удалить из своего местоположения в коллекции, используйте связанный список

-2

Когда следует использовать LinkedList? При работе со стеками в основном или при работе с буферами. Когда следует использовать ArrayList? Только при работе с индексами, в противном случае вы можете использовать HashTable со связанным списком, тогда вы получите:

Таблица хэшей + связанный список

  • Доступ по клавише O (1),
  • Вставить ключом O (1),
  • Удалить ключом O (1)
  • и существует трюк для реализации RemoveAll/SetAll с O (1) при использовании управления версиями

Похоже, это хорошее решение, и в большинстве случаев это так, как вы должны знать: HashTable занимает много места на диске, поэтому, когда вам нужно управлять списком из 1000 000 элементов, это может стать вопросом, который имеет значение. Это может произойти в реализациях сервера, в клиентах это редко бывает.

Также посмотрите Red-Black-Tree

  • Случайный доступ Журнал (n),
  • Вставить Журнал (n),
  • Удалить Журнал (n)
  • 3
    Я хотел бы дать это больше, чем один -1: LinkedList дает O (N) для всех операций вставки, удаления и произвольного доступа, потому что вы должны пройти по списку, чтобы сначала добраться до нужной точки. Также вас может удивить, что в хэш-таблице / таблице используются массивы изменения размеров, такие как ArrayList, и, учитывая, что наиболее распространенное использование списков - просто индексировать их по числу, использование одного из них над ArrayList - худшая идея.
  • 1
    @ Нумерон, ты прав, непонятно, что я ответил. На самом деле, когда вы пытаетесь получить доступ к связанному списку по индексу, это будет O (n), как бы я ни подразумевал вставку в связанный список по элементам. Тогда это O (1), а также взаимодействует по всему списку, так же, как список массивов.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню