我一直是一个简单使用的人:

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

我使用接口作为可移植性的类型名称,这样当我问类似这样的问题时,我就可以修改代码。

LinkedList何时应用于ArrayList,反之亦然?


当前回答

对于ArrayList和LinkedList,remove()和insert()的运行时效率都为O(n)。然而,线性处理时间背后的原因来自两个非常不同的原因:

在ArrayList中,您可以找到O(1)中的元素,但实际上删除或插入某些元素会使其成为O(n),因为以下所有元素都需要更改。

在LinkedList中,实际到达所需元素需要O(n),因为我们必须从一开始就开始,直到达到所需的索引。实际上,移除或插入是常量,因为我们只需要为remove()更改1个引用,为insert()更改2个引用。

插入和删除这两项中的哪一项更快取决于发生的位置。如果我们更接近开始,LinkedList将更快,因为我们必须经过相对较少的元素。如果我们接近末尾,ArrayList将更快,因为我们在恒定的时间内到达那里,只需更改紧随其后的几个剩余元素。如果正好在中间完成,LinkedList将更快速,因为遍历n个元素比移动n个值更快。

好处:虽然无法为ArrayList创建这两个方法O(1),但实际上在LinkedList中有一种方法可以做到这一点。假设我们想在整个列表中删除和插入元素。通常,您可以使用LinkedList从头开始每个元素,我们也可以使用迭代器“保存”当前正在处理的元素。在迭代器的帮助下,当在LinkedList中工作时,remove()和insert()的效率为O(1)。使其成为我所知的唯一性能优势,LinkedList总是优于ArrayList。

其他回答

ArrayList和LinkedList各有利弊。

与使用指向下一个节点的指针的LinkedList相比,ArrayList使用连续内存地址。因此,当您想在ArrayList中查找元素时,比使用LinkedList进行n次迭代更快。

另一方面,LinkedList中的插入和删除要容易得多,因为您只需更改指针,而ArrayList意味着对任何插入或删除都使用移位操作。

如果您的应用程序中有频繁的检索操作,请使用ArrayList。如果频繁插入和删除,请使用LinkedList。

正确或不正确:请在本地执行测试并自行决定!

LinkedList中的编辑/删除速度比ArrayList快。

Array支持的ArrayList需要两倍的大小,在大容量应用程序中更糟糕。

以下是每个操作的单元测试结果。计时单位为纳秒。


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

让我们将LinkedList和ArrayList与以下参数进行比较:

1.实施

ArrayList是列表接口的可调整大小的数组实现,而LinkedList是列表接口的双重链接列表实现。


2.性能

get(int索引)或搜索操作ArrayList get(int索引)操作在恒定时间内运行,即O(1)而LinkedList get(int索引)操作运行时间为O(n)。ArrayList比LinkedList更快的原因是ArrayList对其元素使用基于索引的系统,LinkedList不为其元素提供基于索引的访问,因为它从开始或结束(以较近者为准)迭代以检索指定元素索引处的节点。insert()或add(Object)操作与ArrayList相比,LinkedList中的插入通常很快。在LinkedList中,添加或插入是O(1)操作。在ArrayList中,如果数组已满(即最坏情况),则调整数组大小并将元素复制到新数组会产生额外的成本,这使得ArrayList的加法运算运行时为O(n),否则为O(1)。删除(int)操作LinkedList中的移除操作通常与ArrayList相同,即O(n)。在LinkedList中,有两个重载的移除方法。一个是remove(),没有任何参数,它会删除列表的头部,并在恒定时间O(1)内运行。LinkedList中的另一个重载remove方法是remove(int)或remove(Object),它删除作为参数传递的Object或int。此方法遍历LinkedList,直到找到Object并将其从原始列表中取消链接。因此,该方法运行时为O(n)。在ArrayList中,remove(int)方法涉及将元素从旧数组复制到新的更新数组,因此其运行时为O(n)。


3.反向迭代器

LinkedList可以使用descendingIterator()反向迭代,同时ArrayList中没有descendingIterator(),因此我们需要编写自己的代码以反向遍历ArrayList。


4.初始容量

如果构造函数没有重载,那么ArrayList将创建一个初始容量为10的空列表,而LinkedList只构建没有任何初始容量的空列表。


5.内存开销

与ArrayList相比,LinkedList中的内存开销更大,因为LinkedList的节点需要维护下一个和上一个节点的地址。虽然在ArrayList中,每个索引仅保存实际对象(数据)。


来源

我在这里看到的一个测试只进行一次测试。但我注意到的是,您需要多次运行这些测试,最终它们的时间会收敛。基本上JVM需要预热。对于我的特定用例,我需要向列表中添加/删除项目,该列表将增加到大约500个项目。在我的测试中,LinkedList的发布速度更快,LinkedList约为50000 NS,ArrayList约为90000NS。。。给予或索取。请参见下面的代码。

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

Joshua Bloch,LinkedList的作者:

有人真的使用LinkedList吗?我写的,我从来没有用过。

链接:https://twitter.com/joshbloch/status/583813919019573248

很抱歉,我的答案没有其他答案那样信息丰富,但我认为这是最不言自明的答案。