数组比ArrayList更快吗?

17

我的直觉告诉我数组比ArrayList更快,因为ArrayList是使用数组来实现的,而数组在填充/丢失元素时会调整大小。

我只是想确认这是否正确,即如果你知道要保存的元素数量,就没有理由使用ArrayList。


2
如果你能保证这一点,出于性能原因,你可以使用数组。然而,我只会在你知道它是性能瓶颈的情况下这样做,因为这会使你的代码不够灵活。过早地进行优化是万恶之源。 - Ruan Mendes
8个回答

29

任何性能差异都将是微不足道的,特别是如果你使用 initialCapacity 初始化你的 ArrayList。 以最易读和易于维护的方式编写代码,并尽量避免优化这种东西,除非你经过测试确定它会对性能产生显著影响。

使用 ArrayList 的潜在原因:

  • 有用的方法(contains等)
  • 实现了 IterableCollectionList,因此可以在很多基于接口的 API 调用中使用。
  • 即使你目前“知道”你的集合大小永远不会改变,生活还是会向我们提出意想不到的要求。当没有可辨认的优势时,为什么要将自己锁定在一种模式中呢?

2
性能从来都不可忽视。我按照循环计费 =P - arkon
@b1naryatr0phy,你能详细解释一下循环部分吗? - Peter
@Peter http://en.wikipedia.org/wiki/Cycles_per_instruction - arkon
1
@Peter:当你说一个CPU是2GHz时,这意味着它可以每秒执行20亿次数学运算——换句话说,CPU每两十亿分之一秒“循环”一次。b1narytr0phy开玩笑说他的代码需要多少这样的“循环”就能得到多少报酬。 - StriplingWarrior

7

ArrayList的功能比原始数组更加强大。如果你知道元素数量,可以创建指定大小的ArrayList。

new ArrayList<String>(100);

如果你担心ArrayList和数组之间的速度差异,那么你担心的是错误的事情。它很可能不会成为你代码中的瓶颈。如果它是瓶颈,几乎肯定有比改用数组更好的解决方案。
不要陷入过早优化的陷阱。它会给你的代码带来麻烦。大多数东西并不重要,只有少数几个是重要的。你只能通过对代码进行分析来找到这些重要的部分。试图使每个部分都快速是提高整体速度非常低效的方法。保持简洁、简单的设计更加有效。这将为你在实际需要优化的一两个地方引入优化提供必要的接口。

4

正如其他人已经说过的那样,除非性能基准表明它是一个瓶颈,请使用ArrayList。

是的,由于访问开销,确实存在性能差异,但通常不会显着。唯一的例外是如果您在ArrayList中存储原始类型。这将导致重大的性能损失,因为它将对象转换为/从Object和原始类型。

// easier to work with but slow
ArrayList<Double> slowList;

// faster primitive data array
double[] fasterList;

2

ArrayList在简单的get/set操作上并不比其他更快,但差异非常小,几乎在任何现实情况下都不值得担心。

List API有一些方法可能会用到,即使在您已知大小将被固定的情况下也是如此。例如,考虑 contains()。您还必须在需要 Iterator 或 API 需要 List 的情况下使用 ArrayList -- 即使您知道列表大小是固定的。


1

是的,数组速度更快。如果您运行数值算法,您可以看到明显的加速。

然而,对于普通应用程序,您不必担心它。这是因为大多数运行时间都花在其他事情上。


0

不要过早地优化你的代码,而是使用最适合你代码的数据结构。

正如你所说的经验法则可能是:

  1. 我不知道元素的数量或者它经常变化 => 列表(不要固定实现)

  2. 元素的数量是固定的并且预先已知 => 数组


我认为过早优化的经验法则不适用于改变API的决策。 - Idan Arye
@aetheria 这个规则适用于黑盒函数的主体,其中优化不会影响程序的其他部分,因此您只能在拥有可供分析的工作程序的情况下受益于优化。在API中,虽然您仍然可以从该分析数据中受益,但优化可能会影响程序的其他部分。例如,如果他有一个返回数组ArrayList的函数,并且他想要切换,他必须更改使用该函数的代码,如果该代码返回该数组ArrayList,他必须更改使用该代码的代码等等。 - Idan Arye
我不同意。为了优化而牺牲API的可用性,这并不是没有充分的分析数据和强有力的商业理由就可以轻易实施的事情。即使有这些,几乎肯定还有更好的解决方法——例如以“讲述,而非询问”的方式设计API,使得这样的实现决策更加隐蔽。这并不意味着数组不容易使用。如果它们提高了API的可用性,那很好。但如果您只是出于优化考虑使用它们,并因此使API更难使用,那在我的看法中,这是一个错误的决定。 - ᴇʟᴇvᴀтᴇ
@aetheria 大多数好的编程语言都允许隐藏实现细节 - 这是更好的选择。但我们不是在谈论好的编程语言 - 我们在谈论Java。在Java中,数组与更复杂的集合(如C#中的)不共享接口,泛型不足以处理数组和ArrayList(如C++中的),也不能使用类型推断来隐藏这些细节(如D中的)。Java甚至没有typedefalias来掩盖您实际使用的类型。 - Idan Arye
我不想卷入语言之争。Java允许您隐藏技术细节,也允许您揭示它们。我的意思是,在开发API时,最好不要揭示实现细节。除非有充分的理由,否则绝对不要这样做。“我认为这样会更快”不是一个好理由。 - ᴇʟᴇvᴀтᴇ
让我们在聊天中继续这个讨论。点击此处进入聊天室 - Idan Arye

0
如果您知道数组的大小,并确保它不会扩展或缩小,请使用数组。如果您不知道大小,建议使用数组列表,因为它们更可靠和稳定。如果性能是您唯一关心的问题,那么请继续前进。

-2

数组比数组列表快得多。差异可能达到百分之几百,可能来自JVM优化。如果将数组变量声明为volatile,则可以获得类似的性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接