在Java中,队列的一个实现是“循环数组”,另一个是“链表”。他们有什么不同?
答案 0 :(得分:3)
就它们的使用方式而言,几乎没有任何区别,除非你达到队列的大小限制(我将在一秒内解释......)
至于其他考虑因素:
链表方法很有用,因为您可以动态调整队列大小而不需要额外的努力 - 这是链接列表的基础。当然,这可以通过重新分配数组来复制,但这不是最简单的方法。
此外,在链表中,没有未使用的内存:在循环数组方法中,如果队列的大小小于数组的最大容量,则会出现“空插槽”。但是,这并不意味着链接列表的内存效率更高,因为:
循环阵列方法的优点是没有开销。链表中的每个节点都需要存储对下一个节点的引用 - 如果列表变大,这将加起来。另一方面,循环数组只是一个通过索引访问的内存块,因此没有开销。
每种方法都有赞成和反对意见,但实际上,它归结为它所使用的特定情况......除非你使用队列无止境,否则它可能不会产生太大的影响。
答案 1 :(得分:1)
通常情况下,圆形阵列实现在重用内存方面略胜一筹,但如果将太多项目添加到队列中则存在增长的风险 - 如果正常存储和最大存储容量太大,可能会占用太多内存在实践中有所不同。
链表更灵活,但通常涉及更多垃圾收集。
在实践中,如果您发现代码瓶颈取决于此选择,我会感到惊讶 - 请使用对您来说最直观的代码。
答案 2 :(得分:1)
关于ArrayList和LinkedList之间的差异。
对于阵列,您需要估计队列的大小,因为您需要为其分配存储空间。但是,这样做,在接近容量时更紧凑。 “自由点”仍然占用数组中的空间,而这些空间在LinkedList中没有。
对于链接列表,更容易从中间删除和添加元素(尽管队列根本不需要)。
数组是随机访问,这意味着您可以快速到达位置x的元素。同样,这个功能在队列中没有用。
答案 3 :(得分:0)
实现为链接列表的队列没有固定大小,而实现为循环数组(又称ring buffer)的队列通常具有固定大小(尽管可以调整大小,很像ArrayList调整大小的方式。)
链表实现每个元素使用更多内存,但是数组实现需要更多连续内存。这两个问题实际上只是一个重要问题,因为元素数量变得非常大。
向循环数组实现中添加/删除元素非常便宜,因为它只涉及调整计数器和设置引用,而链接列表实现必须在添加时分配元素,并在删除时产生GC开销。
答案 4 :(得分:0)
编写代码,使其仅使用接口,但创建队列除外。然后很容易切换实现。
选择一个实施作为开始。我通常使用数组变体(例如ArrayList),因为它们更小并且在今天的计算机上往往更快一些,我认为这是由于缓存(我只是做了一些基准测试,通过一个10000元素队列推送10000000个元素,〜 ArrayBlockingQueue为8.3s,LinkedBlockingQueue为10-11s。如果我需要索引访问,我也会使用数组变体。只有在列表或队列中间有大量插入/删除时,我才会选择链接列表变体。
如果您遇到性能问题并且性能分析显示队列是瓶颈(这是不太可能的),请使用队列的两个实现进行基准测试并选择更好的队列。