为什么不总是在Java中使用ArrayLists而不是普通的'数组?

时间:2009-04-04 14:54:05

标签: java

快速提问:为什么不总是在Java中使用ArrayLists?除了额外的有用功能外,它们显然具有与阵列相同的访问速度。我理解它不能保存原语的限制,但使用包装器可以轻松减轻这种情况。

5 个答案:

答案 0 :(得分:11)

许多项目只使用ArrayListHashMap或其他任何项目来处理所有收集需求。但是,让我对此提出一个警告。无论何时在整个代码中创建类并使用它们,如果可能的话,请参考它们实现的接口,而不是用于实现它们的具体类。

例如,而不是:

ArrayList insuranceClaims = new ArrayList();

这样做:

List insuranceClaims = new ArrayList();

甚至:

Collection insuranceClaims = new ArrayList();

如果你的代码的其余部分只通过它实现的接口(ListCollection)知道它,那么如果你发现你需要一个不同的东西,那么将它交换出来用于另一个实现变得更加容易一。我看到这种情况发生在一个月之前,当我需要换出一个常规的HashMap来实现一个实现,它会按照我把它们放入的相同顺序将项目返回给我,以便迭代它们。幸运的是,Jakarta Commons Collections中提供了这样的东西,我只用一行代码更改了A换成B,因为两者都实现了Map。

答案 1 :(得分:8)

如果你需要一组基元,那么数组可能是这项工作的最佳工具。拳击是一项相对昂贵的手术。对于将用作基元的基元的集合(不包括地图),我几乎总是使用数组来避免重复装箱和拆箱。

然而,我很少担心数组和ArrayList之间的性能差异。如果List将提供更好,更清晰,更易维护的代码,那么我将始终使用List(或CollectionSet等,但您的问题大概是ArrayList),除非有一些令人信服的理由不这样做。性能很少那令人信服的理由。

使用Collection几乎总能产生更好的代码,部分原因是因为数组不能很好地使用泛型,正如JohannesWeiß在评论中已经指出的那样,但也是因为有很多其他原因:

  • 集合有一个非常丰富的API和各种各样的实现,可以(在大多数情况下)互相交换进出
  • 如果偶尔使用数组版本很有用,可以将Collection简单地转换为数组
  • 许多集合比数组增长更优雅,这可能是性能问题
  • 收藏品非常适用于泛型,数组非常糟糕
  • 正如TofuBeer所指出的那样,数组协方差很奇怪,并且可以以无法实现的方式行动,没有任何对象可以作用。集合以预期的方式处理协方差。
  • 数组需要根据其任务手动调整大小,如果数组未满,则需要自行跟踪。如果需要调整数组的大小,则必须自己完成。

所有这些在一起,我很少使用数组,只是经常使用ArrayList。但是,我经常使用List(或只是CollectionSet)。我最常使用的数组是当存储的项目是一个基元时,它将被插入并访问并用作基元。如果拳击和拆箱都变得如此之快以至于变得微不足道,我可能会重新审视这个决定,但是以一种始终引用的形式处理某些东西,存储它会更方便。 (即'int'而不是'Integer'。)

答案 2 :(得分:5)

性能不应该是您最关心的问题。

尽可能使用List界面,根据实际需求选择具体实施(ArrayList进行随机访问,LinkedList进行结构修改,......)。

你应该关注表现。

使用数组,System.arraycopyjava.util.Arrays和其他低级内容来挤出最后一滴性能。

答案 3 :(得分:4)

这是过早未优化的情况:-)。你永远不应该做某事,因为你认为它会更好/更快/让你更快乐。

ArrayList有额外的开销,如果你不需要ArrayList的额外功能,那么使用ArrayList是浪费的。

对于你可以用List做的一些事情,还有Arrays类,这意味着ArrayList提供的功能比Arrays更少。现在使用它们可能比使用ArrayList慢,但必须对其进行分析才能确定。

你永远不应该尝试更快地创造一些东西而不确定它开始的速度很慢......这意味着你应该继续使用ArrayList,直到你发现它们是一个问题并减慢程序的速度。但是也应该有常识 - ArrayList有开销,开销很小但是累积。在分析器中发现并不容易,因为它只是在这里有点开销,并且在那里有一点开销。所以常识会说,除非你需要ArrayList的功能,否则你不应该使用它,除非你想要减少数千次(性能明智)。

对于内部代码,如果你发现你确实需要从数组更改为ArrayList,那么在大多数情况下([i]变为get(i),这将是99%的变化)。 / p>

如果您使用for-each外观(for(value:items){}),那么也没有代码可以更改。

另外,按照你的说法去做:

1)访问速度相等,具体取决于您的环境。例如,Android VM没有内联方法(据我所知,它只是一个直接的解释器),因此对它的访问速度要慢得多。 ArrayList上的其他操作可能会导致速度降低,取决于您正在执行的操作,无论VM是什么(使用直接阵列可能更快,您还需要配置或检查源以确保)。

2)Wrappers会增加使用的内存量。

在分析某些内容之前,你不应该担心速度/内存,另一方面,除非你有充分的理由,否则你不应该选择你知道的更慢的选项。

答案 4 :(得分:2)

嗯,不要总是盲目地使用不适合工作的东西。始终使用列表开始,选择ArrayList作为您的实现。这是一种更为面向对象的方法。如果你不知道你特别需要一个数组,你会发现,从长远来看,不要将自己绑定到List的特定实现对你来说会好得多。让它先工作,稍后优化。