这里有个简单的问题:为什么不总是在Java中使用ArrayLists?除了额外的有用功能外,它们显然具有与阵列相同的访问速度.我理解它不能保存基元的限制,但是通过使用包装器可以很容易地减轻这种限制.
很多项目只是使用ArrayList
或者HashMap
用于处理所有收集需求.但是,让我对此提出一个警告.无论何时在整个代码中创建类并使用它们,如果可能的话,请参考它们实现的接口,而不是用于实现它们的具体类.
例如,而不是:
ArrayList insuranceClaims = new ArrayList();
做这个:
List insuranceClaims = new ArrayList();
甚至:
Collection insuranceClaims = new ArrayList();
如果您的代码的其余部分仅通过它实现的接口(List
或Collection
)知道它,那么如果您发现需要另一个实现,那么将其交换为另一个实现将变得更加容易.我看到这种情况发生在一个月之前,当我需要更换一个常规HashMap
的实现时,会按照我将它们放入的相同顺序将项目返回给我,以便迭代所有这些项目.幸运的是,Jakarta Commons Collections中提供了这样的东西,我只用一行代码更换A换了B,因为两者都实现了Map.
如果您需要一组基元,那么数组可能是该工作的最佳工具.拳击是一项相对昂贵的手术.对于将用作基元的基元的集合(不包括地图),我几乎总是使用数组来避免重复装箱和拆箱.
ArrayList
然而,我很少担心数组和数组之间的性能差异.如果一个List
将提供更好,更清洁,更易于维护的代码,那么我将始终使用List
(Collection
或者Set
,等等,但你的问题是关于ArrayList
),除非有一些令人信服的理由不这样做.表现很少是令人信服的理由.
使用Collection
s几乎总能产生更好的代码,部分原因是因为数组不能很好地使用泛型,正如JohannesWeiß在评论中已经指出的那样,还因为有很多其他原因:
集合具有非常丰富的API和各种各样的实现,可以(在大多数情况下)可以互相交换进出
如果偶尔使用数组版本有用,则可以将Collection简单地转换为数组
许多集合比数组增长更优雅,这可能是一个性能问题
集合非常适用于泛型,数组非常糟糕
正如TofuBeer所指出的,数组协方差很奇怪,并且可以以无法实现的方式操作,没有任何对象可以作用.集合以预期的方式处理协方差.
数组需要根据其任务手动调整大小,如果数组未满,则需要自行跟踪.如果需要调整数组的大小,则必须自己完成.
所有这些在一起,我很少使用数组,只是经常使用一个ArrayList
.但是,我List
经常使用s(或只是Collection
或Set
).我最常使用的数组是当存储的项目是一个基元时,它将被插入并访问并用作基元.如果拳击和拆箱都变得如此之快以至于变得微不足道,我可能会重新审视这个决定,但是以一种始终引用的形式处理某些东西,存储它会更方便.(即'int'而不是'Integer'.)
这是过早未优化的情况:-)。您永远不要做某事,因为您认为它会更好/更快/使您更快乐。
ArrayList有额外的开销,如果您不需要ArrayList的其他功能,那么使用ArrayList是浪费的。
同样,对于您可以使用List进行的某些操作,还有Arrays类,这意味着ArrayList提供的功能比Arrays的要少。现在使用它们可能比使用ArrayList慢,但是必须对其进行分析以确保。
在决不确保开始速度不快的情况下,切勿尝试加快速度……这意味着您应该继续使用ArrayList,直到发现它们有问题并降低程序速度。但是也应该有常识-ArrayList有开销,开销很小但是累积的。在探查器中发现它并不容易,因为这里只是一点点开销,而那里只是一点点开销。因此,常识会说,除非您需要ArrayList的功能,否则不应该使用它,除非您想以千篇一律的方式死掉(从性能上考虑)。
对于内部代码,如果发现确实需要从数组更改为ArrayList,则在大多数情况下,这种机会非常简单([i]变为get(i),这将是更改的99%)。
如果您使用的是for-each外观(for(value:items){}),那么也没有代码可以更改。
另外,按照您说的去做:
1)相等的访问速度,具体取决于您的环境。例如,Android VM不内联方法(据我所知,它只是一个直接的解释器),因此对它的访问会慢得多。不管VM是什么,ArrayList上还有其他操作可能会导致速度降低,具体取决于您的操作(对于虚拟阵列而言,这样做可能会更快,因此,必须再次分析或检查源才能确定)。
2)包装器增加了正在使用的内存量。
配置文件之前,您不必担心速度/内存,另一方面,除非有充分的理由,否则您不应该选择较慢的选项。
性能不应该是您的主要关注点。
List
尽可能使用接口,根据实际要求选择具体的实现方式(ArrayList
用于随机访问,LinkedList
用于结构修改等)。
您应该关注性能。
使用数组,System.arraycopy
,java.util.Arrays
和其他低层次的东西挤走的表现最后一滴。