【问题标题】:Measuring time does not confirm LinkedList advantage测量时间并不能证实 LinkedList 的优势
【发布时间】:2013-10-12 11:52:27
【问题描述】:

我正在阅读When to use LinkedList over ArrayList? 中指出的ArrayListLinkedList 之间的差异。我开发了一个小示例应用程序来测试LinkedList 的主要优势,但我得到的结果并不能证实LinkedList 在操作性能上胜过ArrayList

ListIterator.add(E element)

这是我的代码:

public static void main(String[] args) {

        int number = 100000;

        long startTime1 = System.currentTimeMillis();
        fillLinkedList(number);
        long stopTime1 = System.currentTimeMillis();

        long startTime2 = System.currentTimeMillis();
        fillArrayList(number);
        long stopTime2 = System.currentTimeMillis();

        System.out.println(" LinkedList needed: "+ (stopTime1 - startTime1));
        System.out.println(" ArrayList needed: "+ (stopTime2 - startTime2));

    }


    public static void fillLinkedList(int number){

        LinkedList<Integer> list = new LinkedList<Integer>();
        ListIterator<Integer> it = list.listIterator();
        int i = 0;
        while(i++<number){
            it.add(i);
        }
    //  System.out.println("LinkedList size: "+list.size());

    }


    public static void fillArrayList(int number){
        ArrayList<Integer> list = new ArrayList<Integer>();
        ListIterator<Integer> it = list.listIterator();
        int i = 0;
        while(i++<number){
            it.add(i);
        }
    //  System.out.println("ArrayList size: "+list.size());
    }

测量结果:

number            10,000     100,000     500,000      1,000,000     5,000,000

ArrayList            7         17         60             77           170

LinkedList           7         21         89             838          4127

我注意到元素的增加显着削弱了LinkedList 的性能,而ArrayList 表现出明显更好的行为。我理解错了吗?

【问题讨论】:

  • 请注意,对于LinkedList,您需要为每次插入创建一个Node 对象。使用ArrayList,您必须扩大阵列。
  • 你什么都明白。 Stack Overflow 充满了...
  • 对于未来的测量,您可能应该使用System.nanoTime() 而不是System.currentTimeMillis(),因为后者的精度要低得多,而且您实际上并不是在这里测量当前时间,而是 2 之间的差异点。
  • 如果先填充ArrayList,再填充LinkedList,那么结果就大不一样了。 ArrayList 仍然大部分获胜,但更接近。
  • 在这种情况下,为什么你认为LinkedList 应该比ArrayList 快?我在引用的问题中看不到任何支持这一假设的内容。 LinkedListArrayList 具有相同的附加渐近摊销行为。但是,后者的常数因子要小得多。

标签: java arraylist linked-list listiterator


【解决方案1】:

在(数组或列表的)开头或中间的插入和删除是列表击败数组的地方。

【讨论】:

    【解决方案2】:

    ArrayList 在容器末尾或非常接近的位置添加元素时更快,因为它不需要移动很多元素。在中间或开头添加时,它很慢。我将您的循环更改为以下内容:

        while(i++<number){
            it.add(i);
            if(i%2 == 0)
                it.previous();
        }
    

    现在,it 将始终指向list 的中间。有了这个基准,LinkedList 的速度要快得多。 200000 的结果:

    LinkedList needed: 47
    ArrayList needed: 4702
    

    【讨论】:

    • 你能解释一下“现在,它总是指向列表的中间”是什么意思吗?我认为您的代码不会那样做。
    • @arjacsoh - 每秒add 我返回一个元素。实际上我做了 n 次 add,但只前进 n/2 次。
    • 这是对的,但与您声称的“现在,它将始终指向列表的中间”不同。
    • @arjacsoh,如果你想让我说得非常准确的话:在循环的每次迭代之后,it 将指向索引为 (list.size()+1)/2 的元素。
    【解决方案3】:

    据我了解,LinkedList 的好处在于将值插入给定索引(例如,中间或开头)。 ArrayList 不会因顺序插入而失败,因为它不必将元素移过来。

    按照上述方式填充列表后,请查看针对不同位置的就位插入所获得的结果。我已经修改了您的示例,以显示 LinkedList 显着获胜的示例(至少在我的设置中):

    public static void main(String[] args) {
    
        int number = 5000000;
    
        LinkedList<Integer> llist = new LinkedList<Integer>();
        ArrayList<Integer> alist = new ArrayList<Integer>();
    
        long startTime1 = System.nanoTime();
        fillLinkedList(number, llist);
        long stopTime1 = System.nanoTime();
    
        long startTime2 = System.nanoTime();
        fillArrayList(number, alist);
        long stopTime2 = System.nanoTime();
    
        System.out.println(" LinkedList needed: "+ (stopTime1 - startTime1));
        System.out.println(" ArrayList needed: "+ (stopTime2 - startTime2));
    
        startTime1 = System.nanoTime();
        llist.add(1, 4);
        stopTime1 = System.nanoTime();
    
        startTime2 = System.nanoTime();
        alist.add(1, 4);
        stopTime2 = System.nanoTime();
    
        System.out.println(" LinkedList needed: "+ (stopTime1 - startTime1));
        System.out.println(" ArrayList needed: "+ (stopTime2 - startTime2));
    
    }
    
    public static void fillLinkedList(int number, LinkedList<Integer> list){
    
    
        ListIterator<Integer> it = list.listIterator();
        int i = 0;
        while(i++<number){
            it.add(i);
        }
        //  System.out.println("LinkedList size: "+list.size());
    
    }
    
    
    public static void fillArrayList(int number, ArrayList<Integer> list){
        ListIterator<Integer> it = list.listIterator();
        int i = 0;
        while(i++<number){
            it.add(i);
        }
        //  System.out.println("ArrayList size: "+list.size());
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-26
      • 2019-10-20
      • 2015-07-29
      • 2010-10-20
      • 2011-03-21
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 2016-10-06
      相关资源
      最近更新 更多