我试图理解为什么Java的ArrayDeque比Java的LinkedList更好,因为它们都实现了Deque接口。我几乎没有看到有人在他们的代码中使用ArrayDeque。如果有人更多地阐明ArrayDeque是如何实现的,那将是有帮助的。如果我理解了它,我会更有信心使用它。我不能清楚地理解JDK实现,因为它管理头部和尾部引用的方式。
mzsu5hc01#
链接结构可能是最不适合在每个元素上进行缓存未命中迭代的结构。除此之外,它们还消耗更多的内存。如果你需要添加/删除两端,ArrayDeque明显优于链表。随机访问每个元素对于循环队列也是O(1)。链表唯一更好的操作是在迭代过程中删除当前元素。
iqxoj9l92#
我认为LinkedList的主要性能瓶颈是,无论何时推到deque的任何一端,在后台实现都会分配一个新的链表节点,这基本上涉及JVM/OS,而且代价很高。此外,无论何时从任何一端弹出,LinkedList的内部节点都有资格进行垃圾收集,这在后台需要更多的工作。由于链表节点被分配在不同的地方,CPU缓存的使用不会带来太多的好处。如果你感兴趣的话,我有一个证明,向ArrayList或ArrayDeque添加(追加)一个元素是在摊销常数时间内运行的;请参阅this。
LinkedList
ArrayList
ArrayDeque
rkttyhzu3#
所有批评LinkedList的人,想想其他在Java中使用List的人可能大多数时候都在使用ArrayList和LinkedList,因为它们在Java 6之前就已经存在了,而且大多数书籍都是以这些为起点的。但是,这并不意味着我会盲目地站在LinkedList或ArrayDeque一边。如果你想知道,看看下面的基准测试done by Brian(存档)。测试设置考虑:
List
测试结果:
图表:
外卖:
vaj7vani4#
ArrayDeque和LinkedList实现了Deque接口,但实现方式不同。请参阅Oracle documentation了解更多详细信息。主要区别:
g6baxovj5#
ArrayDeque是Java 6中的新特性,这就是为什么很多代码(尤其是试图与早期Java版本兼容的项目)不使用它的原因。在某些情况下,它“更好”,因为您没有为每个要插入的项分配一个节点;相反,所有元素都存储在一个巨大的数组中,如果它变满了,就会调整大小。
ubbxdtey6#
我不认为ArrayDeque比LinkedList好,它们是不同的。ArrayDeque的平均速度比LinkedList快。但是对于添加元素,ArrayDeque需要摊销常数时间,LinkedList需要常数时间。对于时间敏感的应用程序,要求所有操作都需要恒定的时间,只能使用LinkedList。ArrayDeque的实现使用数组,需要调整大小,偶尔,当数组已满,需要添加一个元素时,调整大小将花费线性时间,导致add()方法花费线性时间。如果应用程序对时间非常敏感,这可能是一场灾难。关于Java实现这两种数据结构的更详细的解释可以在普林斯顿大学Coursera上的“Algorithms, Part I”课程中找到,该课程由韦恩和Sedgewick教授。该课程对公众免费。在“第2周”的“堆栈和队列”部分的视频“调整阵列大小”中解释了详细信息。
add()
yrdbyhpb7#
虽然**ArrayDeque<E>和LinkedList<E>都实现了Deque<E>接口,但ArrayDeque基本上是用Object数组E[]**来保存Object内部的元素,所以一般用index来定位头尾元素。总而言之,它的工作原理和Deque类似(使用了所有Deque的方法),但是使用了数组的数据结构。至于哪一种更好,取决于你如何使用它们以及在哪里使用它们。
ArrayDeque<E>
LinkedList<E>
Deque<E>
E[]
swvgeqrz8#
并不总是这样。例如,在下面的例子中,根据leetcode 103,linkedlist比ArrayDeque具有更好的性能。
linkedlist
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public List<List<Integer>> zigzagLevelOrder(TreeNode root) { List<List<Integer>> rs=new ArrayList<>(); if(root==null) return rs; // 👇 here ,linkedlist works better Queue<TreeNode> queue=new LinkedList<>(); queue.add(root); boolean left2right=true; while(!queue.isEmpty()) { int size=queue.size(); LinkedList<Integer> t=new LinkedList<>(); while(size-->0) { TreeNode tree=queue.remove(); if(left2right) t.add(tree.val); else t.addFirst(tree.val); if(tree.left!=null) { queue.add(tree.left); } if(tree.right!=null) { queue.add(tree.right); } } rs.add(t); left2right=!left2right; } return rs; } }
3lxsmp7m9#
时间复杂度为O(1),而时间复杂度为O(N)。ArrayDeque不是线程安全的,所以需要手动同步,这样你就可以通过多个线程访问它,所以它们更快。
9条答案
按热度按时间mzsu5hc01#
链接结构可能是最不适合在每个元素上进行缓存未命中迭代的结构。除此之外,它们还消耗更多的内存。
如果你需要添加/删除两端,ArrayDeque明显优于链表。随机访问每个元素对于循环队列也是O(1)。
链表唯一更好的操作是在迭代过程中删除当前元素。
iqxoj9l92#
我认为
LinkedList
的主要性能瓶颈是,无论何时推到deque的任何一端,在后台实现都会分配一个新的链表节点,这基本上涉及JVM/OS,而且代价很高。此外,无论何时从任何一端弹出,LinkedList
的内部节点都有资格进行垃圾收集,这在后台需要更多的工作。由于链表节点被分配在不同的地方,CPU缓存的使用不会带来太多的好处。如果你感兴趣的话,我有一个证明,向
ArrayList
或ArrayDeque
添加(追加)一个元素是在摊销常数时间内运行的;请参阅this。rkttyhzu3#
所有批评
LinkedList
的人,想想其他在Java中使用List
的人可能大多数时候都在使用ArrayList
和LinkedList
,因为它们在Java 6之前就已经存在了,而且大多数书籍都是以这些为起点的。但是,这并不意味着我会盲目地站在
LinkedList
或ArrayDeque
一边。如果你想知道,看看下面的基准测试done by Brian(存档)。测试设置考虑:
测试结果:
图表:
外卖:
ArrayList
或ArrayDeque
,并且由于严格的内存限制,可能需要对列表的最大容量进行很好的猜测。LinkedList
编写的,所以在决定使用ArrayDeque
时要小心,特别是因为它不实现List
接口(我认为这是一个足够大的理由)。可能是你的代码库与List接口进行了广泛的对话,最有可能的是,您决定使用ArrayDeque
。将其用于内部实现可能是个好主意...vaj7vani4#
ArrayDeque和LinkedList实现了Deque接口,但实现方式不同。
请参阅Oracle documentation了解更多详细信息。
主要区别:
1.ArrayDeque 比 LinkedList 在两端的添加和删除操作更有效,LinkedList实现在迭代期间删除当前元素更有效
1.LinkedList 实现比 ArrayDeque 消耗更多内存
因此,如果你不需要支持NULL元素,并且希望内存更少,并且在两端添加/删除元素的效率更高,那么 ArrayDeque 是最好的选择
g6baxovj5#
ArrayDeque
是Java 6中的新特性,这就是为什么很多代码(尤其是试图与早期Java版本兼容的项目)不使用它的原因。在某些情况下,它“更好”,因为您没有为每个要插入的项分配一个节点;相反,所有元素都存储在一个巨大的数组中,如果它变满了,就会调整大小。
ubbxdtey6#
我不认为
ArrayDeque
比LinkedList
好,它们是不同的。ArrayDeque
的平均速度比LinkedList
快。但是对于添加元素,ArrayDeque
需要摊销常数时间,LinkedList
需要常数时间。对于时间敏感的应用程序,要求所有操作都需要恒定的时间,只能使用
LinkedList
。ArrayDeque
的实现使用数组,需要调整大小,偶尔,当数组已满,需要添加一个元素时,调整大小将花费线性时间,导致add()
方法花费线性时间。如果应用程序对时间非常敏感,这可能是一场灾难。关于Java实现这两种数据结构的更详细的解释可以在普林斯顿大学Coursera上的“Algorithms, Part I”课程中找到,该课程由韦恩和Sedgewick教授。该课程对公众免费。
在“第2周”的“堆栈和队列”部分的视频“调整阵列大小”中解释了详细信息。
yrdbyhpb7#
虽然**
ArrayDeque<E>
和LinkedList<E>
都实现了Deque<E>
接口,但ArrayDeque基本上是用Object数组E[]
**来保存Object内部的元素,所以一般用index来定位头尾元素。总而言之,它的工作原理和Deque类似(使用了所有Deque的方法),但是使用了数组的数据结构。至于哪一种更好,取决于你如何使用它们以及在哪里使用它们。
swvgeqrz8#
并不总是这样。
例如,在下面的例子中,根据leetcode 103,
linkedlist
比ArrayDeque
具有更好的性能。3lxsmp7m9#
时间复杂度为O(1),而时间复杂度为O(N)。ArrayDeque不是线程安全的,所以需要手动同步,这样你就可以通过多个线程访问它,所以它们更快。