【问题标题】:How the ArrayList add() behavesArrayList add() 的行为方式
【发布时间】:2015-08-20 16:05:18
【问题描述】:

考虑以下两个代码sn-ps:

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0);
for (int i=1; i<10; i++)
    list.add(i);

ArrayList<Integer> list = new ArrayList<Integer>();
for (int i=1; i<10; i++)
    list.add(i);
list.add(0,0);

我真的很想知道这两种情况是否有任何性能差异?我在想的是 ArrayList 实际上是一个 Object[] ......所以第二个代码 sn-p 需要将原始数组复制到某个地方,然后在位置 0 处创建一个带有 '0' 的新数组......所以我认为第一种方法确实更好?

【问题讨论】:

  • 担心这个级别的性能差异几乎毫无意义。如果您有一个完整的项目-并且-分析表明您在模块中存在性能问题...-那么-考虑微优化是合理的。上面代码 sn-ps 的差异可能非常小。

标签: java arrays performance arraylist


【解决方案1】:

...所以第二个代码 sn-p 需要将原始数组复制到某个地方,然后在位置 0 处创建一个带有 '0' 的新数组...

如果它在当前的空间中有足够的空间,则不必分配一个(使用该代码,它将使用 Oracle 的实现——只是,它的初始容量默认为 10 )。但它确实必须洗牌。

...所以我认为第一种方法确实更好?

当然,并且出于您给出的原因。第二个块只是不必要地使ArrayList 在底层数组中移动。

(并不是说它可能很重要,除非这是一个非常紧密的循环,被运行了数百万次......但仍然如此。)

【讨论】:

    【解决方案2】:

    第一个选项更好。一般来说顺序访问更快,但第一个例子也更清楚恕我直言。

    如果你真的想知道,你可以查看来源,但是

    list.add(0, 0);
    

    将元素向下移动到底层数组。如果它没有足够的容量,它只会创建一个新数组,就像list.add(i) 必须做的那样。

    【讨论】:

      【解决方案3】:

      第二种方法将移动 Arraylist 中的其他元素,从而引入了性能问题。见this doc link。只有在没有空间的情况下才会创建新数组。

      【讨论】:

        【解决方案4】:

        第一种方法只是更好的做法,但在这种情况下,两者都没有明显的优势。尽管其他答案怎么说,ArrayLists 插入一个元素无论在哪里都不需要时间。也就是说,在开头插入0是不变的。请注意,如果您要插入多个元素,则时间为 O(n),其中 n 是您要插入的项目数。

        当我对这两个代码 sn-ps 运行一些测试时,结果如下:

        794913915
        703911773
        

        838856889
        942264566
        

        因此您可以看到,当您插入一个元素时,这并不重要。注意:此测试插入 100 项目而不是 10,但 10 的结果是相同的。但是,如果我们运行相同的测试,除了第一种情况先插入100 项,第二种情况稍后在列表开头插入100 项,结果如下:

        1316759001
        8390794221
        

        “更好的实践”方法花费的时间要少得多。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-23
          • 1970-01-01
          • 2016-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-03
          • 1970-01-01
          相关资源
          最近更新 更多