在我用无意义的重言式杀死你之前,这是要点
- 如果您的应用程序接近实时,或者将代码发送到Mars,则需要保留Java中默认的Stack实现。 根据
LinkedList
编写您自己的版本。 - 同样,如果您的应用程序是关键任务,并且希望堆栈由并发线程处理,则使用
ConcurrentLinkedDeque
或基于LinkedList
编写自己的Stack
-只需确保添加和删除操作是线程安全的即可。 这样做时,请考虑并发锁 。 - 您只需要原始电源,并且在
push
过程中不会被偶尔的打扰所困扰,并且您的Stack
不会被并发线程操纵,然后使用ArrayDeque
或继续基于ArrayList
编写自己的Stack。 - 如果是多线程的,则根据
ArrayQueue
和util.concurrent锁编写自己的Stack
。 - 如果您拒绝阅读Java Stack API和Java Deque API,而您只是个疯子,那么请使用默认实现。 而且,我保证,当机器人占领世界时,不会显示怜悯之心。
注意:事实是,除非出于某种原因,您想要将实现类命名为' Stack ',否则您可以自由地将所有Deque实现直接用作Stack。
既然已经对默认实现抛出了足够多的麻烦,请注意几分钟,让我快速总结一下。
我们知道Java Collection API中的Stack
是从Vector
内部扩展的, Vector
在内部使用数组。 换句话说,Java将基于数组的实现用于其Stack
。
因此,让我们看看为什么在两个最受欢迎的Stack
实现之间-数组和链表,Java选择了数组。
有些答案很明显,有些则没有:
公平竞争
粗略地看一下数组和链表的add
和remove
方法(它们是Stack
的push
和pop
方法的Struts),可以在整个板上进行恒定时间的检索。
增长问题
数组是固定大小的,并且仅通过将数组复制到更大的数组即可实现数组的增长 ,这并不是什么新闻。 在我们默认使用Vector实现Stack的情况下,增量容量仅为两倍。
这只是意味着,如果我们要向堆栈中添加80个元素,则内部数组将被复制4次–分别为10、20、40和80。因此,也就是说,当我们添加第80个元素时,push操作实际上需要O(N )时间,因为在这种情况下,我们的N为80,所以使用该残酷的深层副本将使您的程序至少稍稍停顿一下–您可以节省其他宝贵时间的宝贵小循环。
遗憾的是,与Vectors不同,您将无法指定java.util.Stack
的初始大小或增量因子,因为没有重载的构造函数。
另一方面,尽管增长经常会ArrayQueue
,但ArrayQueues的初始容量有一个甜美的重载构造函数,如果您对堆栈的大小有一个大概的了解,这将派上用场。 此外,默认初始容量是16用于ArrayQueue
用于作为对10 Vector
。
时间和地点,我的朋友。 时间和地点
为了与数组公平,存储在基于数组的堆栈中的对象只是对堆中实际对象(对于对象而言)或实际值(对于基元而言)的引用。
另一方面,在LinkedList的情况下,存储项目的顶部上方有一个Node
包装器。 平均而言,每个存储的对象(包括Node对象的内部类,链接到下一个Node以及对项本身的引用)将在堆中花费约40字节的额外空间。
那么,ArrayQueue或LinkedList吗?
数组在大多数情况下都是首选的,因为它们具有占用顺序存储器的独特优势,并且它们提供了更快的访问速度,而到达实际对象只是指针运算。 但是,对阈值项目(触发调整大小的项目)的push
和pop
操作需要O(n)
时间。 但是,平均而言,它需要花费固定时间(如果需要,可以摊销固定时间)。
另一方面,使用LinkedList
,由于要花费更多的时间来构造新节点并指向新节点,所以add
操作比数组要慢。 不用说,新节点消耗的堆空间不是实际对象消耗的空间。 但是,由于没有大小调整(或需要顺序存储),并且总是引用第一个元素,因此最坏的情况是保证了恒定的时间。
现在,当您重新访问本博客的第一部分时,请随意说该死,默认实现!!!
相关链接 :
- http://onjava.com/pub/a/onjava/2001/10/23/optimization.html
- http://www.javaworld.com/javatips/jw-javatip130.html?page=1
- http://docs.oracle.com/javase/7/docs/api/java/util/RandomAccess.html
- http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Vector.java
参考资料: 为什么我们的JCG合作伙伴 Arun Manivannan会使用Rerun.me博客中的后代 人 讨厌使用java.util.Stack 。
翻译自: https://www.javacodegeeks.com/2012/11/why-future-generations-will-hate-you-for-using-java-util-stack.html