与Array列表相比,为什么在Linked列表的末尾插入的速度很慢

时间:2014-02-22 07:48:01

标签: java collections

即使链接列表在内部使用双向链接列表,因此它可以轻松识别最后一个元素并开始添加。现在它仍然比数组列表慢吗?

请参考以下代码并输出:

package com.collection;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Performance {

    public static void main(String[] args) {
        List<Integer> arrayList = new ArrayList<Integer>();
        List<Integer> LinkedList = new LinkedList<Integer>();
        checkPerformance("arrayList", arrayList);
        checkPerformance("LinkedList", LinkedList);
    }

    private static void checkPerformance(String type, List<Integer> list) {
        for (int i = 0; i < 1E6; i++) {
        list.add(i);
        }
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1E6; i++) {
            list.add(i);
        }
        long end = System.currentTimeMillis();
        System.out.println("Time Taken" + " " + (end - start)
        + " ms for the type " + type);
    }
}

输出: 类型arrayList的时间为250毫秒 LinkedList

类型的时间为390毫秒

2 个答案:

答案 0 :(得分:2)

所以,我认为你假设ArrayList会慢一些,因为它必须分配一个新数组并在每次向其中添加一个元素时将旧数组复制到新数组中,但事实并非如此

将元素添加到ArrayList时,此元素将添加到经典数组中,但在此之前,它会调用以下方法以确保后备数组的大小足以添加元素: / p>

/**
 * Increases the capacity of this <tt>ArrayList</tt> instance, if
 * necessary, to ensure that it can hold at least the number of elements
 * specified by the minimum capacity argument.
 *
 * @param   minCapacity   the desired minimum capacity
 */
public void ensureCapacity(int minCapacity) {
    modCount++;
    int oldCapacity = elementData.length;
    if (minCapacity > oldCapacity) {
        Object oldData[] = elementData;
        int newCapacity = (oldCapacity * 3)/2 + 1;
        if (newCapacity < minCapacity)
        newCapacity = minCapacity;
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
}

这意味着,如果支持数组的大小不足以添加您的元素,则不会像您期望的那样将大小增加到oldCapacity + 1,而是(oldCapacity * 3)/2 + 1,允许您向其中添加更多元素,而无需再次分配和复制它。

在第一个循环结束时,数组的容量将为 1005308 (您可以通过在循环后设置断点并检查列表变量来检查它)。 因此,要添加1000000个元素,您将只重新分配两次:一个从 1005308 1507963 ,一个从 1507963 2261945 。剩下的时间,你只需将支持数组中的一个元素设置为另一个值(它真的很便宜)。

另一方面,使用LinkedList,每次向列表添加内容时都必须分配一个新元素,并且您将有更多操作(设置值,并更改两个指针值) ,这就是为什么它比ArrayList需要更多的时间(我试过,LinkedList对我来说更快)。

答案 1 :(得分:1)

事实上,这对我来说完全不同,而且每件事都符合预期: 类型arrayList的时间为184毫秒 LinkedList类型的时间为31毫秒

我甚至测试了这个:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class TestClass   {

    public static void main(String[] args) {
        List<Integer> arrayList = new ArrayList<Integer>();
        List<Integer> LinkedList = new LinkedList<Integer>();
        checkPerformance("arrayList", arrayList);
        checkPerformance("LinkedList", LinkedList);
    }
    private static void checkPerformance(String type, List<Integer> list) {
        for (int i = 0; i < 1E4; i++) {
            list.add(i);
        }
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1E4; i++) {
            list.get(i);
        }
        long end = System.currentTimeMillis();
        System.out.println("Time Taken" + " " + (end - start)
                + " ms for the type " + type);
    }
}

结果: 类型arrayList的时间为1毫秒 LinkedList类型的时间为82毫秒 正如所料!