为什么数组比ArrayList快得多?

时间:2011-04-27 07:16:42

标签: java performance

最近,我试图解决Problem 23 of Project Euler。为此,我首先创建一个名为abundants的所有大量数字的列表。

接下来,我遍历此列表并构建另一个列表,其中列出了大于某个限制的所有大量数字。现在我发现了一些奇怪的事我使用嵌套循环在列表上迭代两次。但是如果我使用数组存储总和需要几秒钟,如果我将总和添加到ArrayList则需要几个小时。这是什么原因?我认为昂贵的操作是两个嵌套循环,但似乎昂贵的操作是ArrayList #add。任何暗示为什么会这样?

这里是数组的代码:

for (int i = 0; i < abundants.size(); i++) {
   for (int j = 0; j < abundants.size(); j++) {
      int tot = abundants.get(i) + abundants.get(j);
      if (tot <= limit)
         isSum[tot] = true;
      }
   }
}

这里是ArrayList的代码:

ArrayList<Integer> sums = new ArrayList<Integer>();
for (int i = 0; i < abundants.size(); i++) {
   for (int j = 0; j < abundants.size(); j++) {
      int s = abundants.get(i) + abundants.get(j);
      if (!sums.contains(s) && s < limit) {
         sums.add(s);
      }
   }
 }

5 个答案:

答案 0 :(得分:17)

您的ArrayList实现是O(n ^ 3)而另一个是O(n ^ 2):sums.contains(...)必须遍历内循环的每次迭代的整个sums列表。

答案 1 :(得分:6)

我认为你的问题在于ArrayList#contains,它必须遍历整个列表,从而将你的复杂性提高到O(n ^ 3),而不是程序的O(n ^ 2)# 1。

答案 2 :(得分:3)

您的代码不相同,.contains()比使用原始数组的代码贵。每次调用.contains()遍历整个数组时,不要在基于原始数组的版本中执行此操作。

答案 3 :(得分:2)

因为int可能比Integer快得多。

尝试在第一种情况下使用Integer[]或在第二种情况下使用TIntArrayList进行比较。

答案 4 :(得分:-1)

如果您知道(最大)元素数,请尝试使用给定大小初始化Array列表:

ArrayList<Integer> sums = new ArrayList<Integer>(abundants.size() * abundants.size());

由于不需要调整ArrayList的大小,这将提高速度。