快速提问:为什么不总是在Java中使用ArrayLists?除了额外的有用功能外,它们显然具有与阵列相同的访问速度。我理解它不能保存原语的限制,但使用包装器可以轻松减轻这种情况。
答案 0 :(得分:11)
许多项目只使用ArrayList
或HashMap
或其他任何项目来处理所有收集需求。但是,让我对此提出一个警告。无论何时在整个代码中创建类并使用它们,如果可能的话,请参考它们实现的接口,而不是用于实现它们的具体类。
例如,而不是:
ArrayList insuranceClaims = new ArrayList();
这样做:
List insuranceClaims = new ArrayList();
甚至:
Collection insuranceClaims = new ArrayList();
如果你的代码的其余部分只通过它实现的接口(List
或Collection
)知道它,那么如果你发现你需要一个不同的东西,那么将它交换出来用于另一个实现变得更加容易一。我看到这种情况发生在一个月之前,当我需要换出一个常规的HashMap
来实现一个实现,它会按照我把它们放入的相同顺序将项目返回给我,以便迭代它们。幸运的是,Jakarta Commons Collections中提供了这样的东西,我只用一行代码更改了A换成B,因为两者都实现了Map。
答案 1 :(得分:8)
如果你需要一组基元,那么数组可能是这项工作的最佳工具。拳击是一项相对昂贵的手术。对于将用作基元的基元的集合(不包括地图),我几乎总是使用数组来避免重复装箱和拆箱。
然而,我很少担心数组和ArrayList
之间的性能差异。如果List
将提供更好,更清晰,更易维护的代码,那么我将始终使用List
(或Collection
或Set
等,但您的问题大概是ArrayList
),除非有一些令人信服的理由不这样做。性能很少那令人信服的理由。
使用Collection
几乎总能产生更好的代码,部分原因是因为数组不能很好地使用泛型,正如JohannesWeiß在评论中已经指出的那样,但也是因为有很多其他原因:
所有这些在一起,我很少使用数组,只是经常使用ArrayList
。但是,我经常使用List
(或只是Collection
或Set
)。我最常使用的数组是当存储的项目是一个基元时,它将被插入并访问并用作基元。如果拳击和拆箱都变得如此之快以至于变得微不足道,我可能会重新审视这个决定,但是以一种始终引用的形式处理某些东西,存储它会更方便。 (即'int'而不是'Integer'。)
答案 2 :(得分:5)
性能不应该是您最关心的问题。
尽可能使用List
界面,根据实际需求选择具体实施(ArrayList
进行随机访问,LinkedList
进行结构修改,......)。
你应该关注表现。
使用数组,System.arraycopy
,java.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的特定实现对你来说会好得多。让它先工作,稍后优化。