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

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

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

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

когда LinkedList использоваться по ArrayList и наоборот?

30 ответов


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


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

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

на LinkedList<E>

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

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

на ArrayList<E>

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

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

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

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


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

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

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

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


Graph of LinkedList and ArrayList No. of Elements x Bytes


результат ясно показывает, что 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)

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

почему LinkedList хреново:

  • он использует множество небольших объектов памяти и, следовательно, влияет на производительность процесса.
  • много мелких объектов, плохо для кэш-район.
  • любая индексированная операция требует обхода, т. е. имеет производительность O(n). Это не очевидно в исходном коде, что приводит к алгоритмам O (n) медленнее, чем if ArrayList был используемый.
  • получение хорошей производительности сложно.
  • даже если производительность big-O такая же, как ArrayList, Это, вероятно, будет значительно медленнее в любом случае.
  • это раздражает видеть LinkedList в источнике, потому что это, вероятно, неправильный выбор.

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

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

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


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 Обозначения

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


Да, я знаю, это древний вопрос, но я добавлю свои пять копеек:

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

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


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

массив против ArrayList против LinkedList против Vector идет более глубоко, как делает Список Ссылок.


правильно или неправильно: пожалуйста, выполните тест локально и решить для себя!

редактировать / удалить быстрее в 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);
    }
}

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

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

LinkedList быстрее в add и remove, но медленнее в get. Короче говоря, LinkedList следует предпочесть, если:

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

=== ArrayList ===

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

=== LinkedList ===

  • добавить(E e)

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

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

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

enter image description here


ArrayList случайно можно, а LinkedList действительно дешево развернуть и удалить элементы. В большинстве случаев, ArrayList - Это хорошо.

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


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.

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

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

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

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

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

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

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

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


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

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

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

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


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


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

и конечно гуавы ' s ImmutableList ваш лучший друг.


вот обозначение 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)

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


давайте сравним LinkedList и ArrayList w.r.т. ниже параметры:

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

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

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


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

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

    ArrayList с операция get (int index) выполняется в постоянное время i.e O (1) while

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

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

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

  • операция insert () или add (Object)

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

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

  • удалить (int) операция

    операция удаления в LinkedList обычно совпадает с ArrayList, т. е. O (n).

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

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


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

LinkedList может быть повторен в обратном направлении с помощью descendingIterator () в то время как

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


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

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

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


5. Памяти

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

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


источник


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

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



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

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


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

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

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


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

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

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

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


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

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


операция get (i) в ArrayList выполняется быстрее, чем LinkedList, потому что:
ArrayList: Resizable-array реализация интерфейса списка
LinkedList: Двусвязная реализация списка интерфейсов List и Deque

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


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.

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

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

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

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

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

  • и ArrayList и LinkedList являются реализацией интерфейса списка.
  • они оба поддерживают порядок вставки элементов, что означает, что при отображении элементов ArrayList и LinkedList результирующий набор будет иметь тот же порядок, в котором элементы были вставлены в список.
  • оба этих класса не синхронизированы и можно явно синхронизировать с помощью коллекций.способ 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 будет вашим лучшим ставка.


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

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

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

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


1) Базовая Структура Данных

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

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

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

4) удаление элемента из позиции

для удаления элемента из a конкретный индекс, например, вызывая 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, так как он должен пройти до этой записи. Хотя в большой o обозначение O(n/2) просто O (n), потому что мы игнорируем константы там.

7) памяти

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

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

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

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

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

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

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


оба 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, мы также можем "сохранить" текущий элемент, над которым мы работаем с итератором. С помощью итератора мы получаем эффективность O(1) для remove() и insert() при работе в LinkedList. Делая это единственным преимуществом производительности, я знаю, где LinkedList всегда лучше, чем ArrayList.


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

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


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

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;
}

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

хэш-таблица + список ссылок

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

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

посмотрите Красно-Черное Дерево

  • произвольный доступ Log (n),
  • вставить Log (n),
  • удалить Log (n)