使用LinkedList或ArrayList进行迭代

时间:2011-12-08 19:26:32

标签: data-structures arraylist linked-list

如果我要向List添加未知数量的元素,并且该列表只会被迭代,那么LinkedList会比特定实例中的ArrayList更好(使用Java,如果它有任何相关性)

4 个答案:

答案 0 :(得分:20)

ArrayListLinkedList之间的性能权衡已经讨论before,但简而言之:ArrayList对于大多数现实生活中的使用场景来说往往更快。 ArrayList将导致更少的内存碎片并且将更好地与垃圾收集器一起使用,它将消耗更少的内存并允许更快的迭代,并且对于在列表末尾发生的插入将更快。

因此,只要列表中的插入始终出现在最后一个位置,就没有理由选择LinkedList - ArrayList是明显的赢家。

答案 1 :(得分:3)

对于迭代,两者在迭代时将具有相同的O(n)复杂度,ArrayList将占用更少的内存BTW。

答案 2 :(得分:2)

好的它已经回答了,但我仍然会尝试说明我的观点。 ArrayList迭代速度比LinkedList快。原因是相同的,因为arrayList由数组支持。让我们试着理解whay数组迭代比linkedList更快。

有两个因素适用于它

  • 数组存储为contiguous memory locations(您可以说是 什么?)
  • 系统缓存比访问内存要快得多

但你可以问一下Cache如何适合这里。检查here,CPU尝试通过在缓存中存储数据来利用缓存。它使用Locality of refrence。现在有两种技术

参考Locality of refrence

  

时间地点       如果在某一点引用了特定的内存位置,则很可能在该位置再次引用相同的位置   不远的将来。相邻之间存在时间上的接近度   引用相同的内存位置。在这种情况下,它是常见的   努力将引用数据的副本存储在特殊内存中   存储,可以更快地访问。时间地点是一个特殊的地方   空间局部性的情况,即预期位置时   与现在的位置相同。

     

空间位置       如果在特定时间引用特定存储位置,则可能是附近的存储器位置   在不久的将来引用。在这种情况下,通常尝试   猜测当前参考区域周围区域的大小和形状   准备更快的访问是值得的。

因此,如果一次访问一个阵列位置,它也会在缓存中加载相邻的内存位置。但等等它不会加载所有。这取决于CACHE_LINES。好CACHE_LINES定义一次可以在缓存中加载多少位。

所以在进一步潜水之前,不要提醒我们知道什么

  • 数组为contiguous memory locations
  • 当访问数组的一个内存位置时,也会加载到内存中
  • 内存中加载的阵列内存位置由CACHE-LINES容量
  • 定义

每当CPU尝试访问内存位置时,都会检查该内存是否已在缓存中。如果它的存在与其cache miss匹配。

因此,根据我们所知道的数组,cache_missrandom memory locations相比linked list更少styleselect。所以这很有意义

最后来自Array_data_structure from Wikipedia它说

  

在元素大小为k的数组中,在具有缓存行的计算机上   B字节的大小,遍历n个元素的数组需要   最小上限(nk / B)缓存未命中,因为其元素占用   连续的记忆位置。这大致是B / k的一个因素   比随机访问n个元素所需的缓存未命中数   记忆位置。因此,对数组进行顺序迭代   在实践中明显比在许多其他数据上迭代更快   结构,一种称为参与区域的属性

我想这可以回答你的问题。

答案 3 :(得分:0)

public List<Integer> generateArrayList(int n) {
    long start = System.nanoTime();
    List<Integer> result = new ArrayList<>();
    for (int i = 0; i < n; i++) {
        result.add(i);
    }
    System.out.println("generateArrayList time: " + (System.nanoTime() - start));
    return result;
}

public List<Integer> generateLinkedList(int n) {
    long start = System.nanoTime();
    List<Integer> result = new LinkedList<>();
    for (int i = 0; i < n; i++) {
        result.add(i);
    }
    System.out.println("generateLinkedList time: " + (System.nanoTime() - start));
    return result;
}

public void iteratorAndRemove(List<Integer> list) {
    String type = list instanceof ArrayList ? "ArrayList" : "LinkedList";
    long start = System.nanoTime();
    Iterator<Integer> ite = list.iterator();
    while (ite.hasNext()) {
        int getDataToDo = ite.next();
        ite.remove();
    }
    System.out.println("iteratorAndRemove with " + type + " time: " + (System.nanoTime() - start));
}

@org.junit.Test
public void benchMark() {
    final int n = 500_000;
    List<Integer> arr = generateArrayList(n);
    List<Integer> linked = generateLinkedList(n);
    iteratorAndRemove(linked);
    iteratorAndRemove(arr);

}

Arraylist可用于获取随机位置值,链表可用于插入,删除操作。上面的代码显示链表的速度比ArrayList快得多,在删除函数链表的速度比arraylist快1000倍,天哪!

generateArrayList time: 15997000
generateLinkedList time: 15912000
iteratorAndRemove with LinkedList time: 14188500
iteratorAndRemove with ArrayList time: 13558249400