稀土掘金 稀土掘金

为什么不推荐 ArrayDeque 代替 Stack

公众号:ByteCode,致力于分享最新技术原创文章,涉及 Kotlin、Jetpack、译文、系统源码、 LeetCode / 剑指 Offer / 多线程 / 国内外大厂算法题 等等一系列文章。

这篇文章源于对 stack-vs-deque 文章的思考,也是对我上一篇文章 算法动画图解 | 被 "废弃" 的 Java 栈,为什么还在用 内容的补充。

通过这篇文章你将学习到以下内容:

  • 为什么不推荐使用 Java 栈
  • JDK 推荐使用 ArrayDeque 代替 Stack 真的合理吗
  • 如何实现一个真正意义上的栈

在开始讨论之前,我们先来简单的回顾上一篇文章的内容。

为什么不推荐使用 Java 栈

栈是 后入先出(LIFO) 的数据结构,入栈通常使用 push 操作,往栈中插入数据到栈底,出栈使用 pop 操作,从栈顶删除数据。

栈是非常好的数据结构,但是 Java 栈的实现,存在以下问题,所以 JDK 不推荐使用 Java 栈。

  • 性能低

性能低是因为 Stack 继承自 Vector, 而 Vector 在每个方法中都加了锁,如下所示:

......
public synchronized void trimToSize() { }

public synchronized void ensureCapacity(int minCapacity) {  }

public synchronized void setSize(int newSize) {  }

public synchronized int capacity() {  }

public synchronized int size() {  }

public synchronized boolean isEmpty() {  }
......

由于需要兼容老的项目,很难在原有的基础上进行优化,因此 Vector 就被淘汰掉了,因此使用 ArrayListCopyOnWriteArrayList 来代替,在线程安全的情况下可以使用 CopyOnWriteArrayList,否则非线程安全的情况下可以使用 ArrayList

  • 破坏了原有的数据结构

栈的定义是在一端进行 pushpop 操作,除此之外不应该包含其他 入栈和出栈 的方法,但是 Stack 继承自 Vector,使得 Stack 可以使用父类 Vector 公有的方法,如下所示。

val stack = Stack<Int>()
stack.push(6)
stack.add(1,10)
stack.removeAt(1)
stack.pop()
stack.addAll(arrayListOf())
......

正如你所见,除了调用 push()pop() 方法之外,还可以调用 addXXX()removeXXX() 等等方法,但是这样会破坏栈原有的结构。所以对于栈的数据结构,不应该有可以在任何位置添加或者删除元素的能力。

JDK 推荐使用 ArrayDeque 代替 Stack

在 JDK 文档中,栈的相关操作应该由 Deque 接口来提供,推荐使用 Deque 的子类 ArrayDeque 代替 Stack。如下图标注部分所示。

使用 Deque 接口来实现栈的功能有以下好处:

  • 速度比 Stack

这个类作为栈使用时可能比 Stack 快,作为队列使用时可能比 LinkedList 快。因为原来的 Java 的 Stack 继承自 Vector,而 Vector 在每个方法中都加了锁,而 Deque 的子类 ArrayDeque 并没有锁的开销。

  • 屏蔽掉无关的方法

原来的 Java 的 Stack,包含了在任何位置添加或者删除元素的方法,这些不是栈应该有的方法,所以需要屏蔽掉这些无关的方法。

声明为 Deque 接口可以解决这个问题,在接口中声明栈需要用到的方法,无需管子类是如何是实现的,对于上层使用者来说,只可以调用和栈相关的方法。

大神不推荐使用 ArrayDeque 代替 Stack

既然使用 Deque 接口来实现栈有这么多好处,那为什么大神不推荐使用 ArrayDeque 代替 Stack。 baddotrobot.com/blog/2013/0…

因为接口 Deque 是双端队列的线性数据结构, 也就是说可以在两端进行插入和删除操作。而栈只能在一端做插入和删除操作。

栈的定义是在一端进行 pushpop 操作,除此之外不应该包含其他 入栈和出栈 的方法,但是基于 Deque 接口来实现栈,还可以在另外一端进行操作,如下所示。

val stack: Deque<Int> = ArrayDeque()
stack.push(1)
stack.poll() // 栈为空时会抛出异常
stack.peek() // 栈为空时返回 null

stack.offerLast(2)
stack.pollLast()
stack.peekLast()

如上所示,还可以调用 offerLast()pollLast()peekLast() 等等方法,往队列的另一端插入数据。

如果是在做算法题目无论使用 ArrayDeque 还是 Stack 都可以,因为关注点不一样,在做算法题的时候,关注点在解决问题的算法逻辑思路上。但是在大型的项目中不建议直接使用 Stack,也不推荐使用 ArrayDeque 代替 Stack。我们可以基于 ArrayDeque 封装一个真正的栈,只允许在一端做插入和删除操作,如下所示。

interface Stack<E> {
    fun push(e: E)
    fun pop(): E?
    fun peek(): E?
    fun size(): Int
    fun empty(): Boolean
}

class ArrayStack<E> : Stack<E> {

    private val deque = ArrayDeque<E>()

    override fun push(e: E) = deque.push(e)

    override fun pop(): E? = deque.poll()

    override fun peek(): E? = deque.peek()

    override fun size() = deque.size

    override fun empty(): Boolean = deque.isEmpty()

}

如果有帮助 点个赞 就是对我最大的鼓励

代码不止,文章不停

欢迎关注公众号:ByteCode,查看最新技术文章


最后推荐我一直在更新维护的项目和网站:

  • 个人博客,将所有文章进行分类,欢迎前去查看 hi-dhl.com

  • 更多 Kotlin 、Jetpack 实战开源项目,欢迎前往查看 github

  • LeetCode / 剑指 offer / 国内外大厂面试题 / 多线程 题解,语言 Java 和 kotlin,包含多种解法、解题思路、时间复杂度、空间复杂度分析

    • 剑指 offer 及国内外大厂面试题解: 在线阅读
    • LeetCode 系列题解: 在线阅读

近期必读热门文章

  • 算法动画图解 | 被 "废弃" 的 Java 栈,为什么还在用
  • 影响性能的 Kotlin 代码(一)
  • Jetpack Splashscreen 解析 | 助力新生代 IT 农民工 事半功倍
  • 为数不多的人知道的 Kotlin 技巧及解析(三)
  • 为数不多的人知道的 Kotlin 技巧以及 原理解析(二)
  • 为数不多的人知道的 Kotlin 技巧以及 原理解析(一)
  • 揭秘 Kotlin 中的 == 和 ===
  • Kotlin 密封类进化了
  • Kotlin 中的密封类 优于 带标签的类
  • Kotlin Sealed 是什么?为什么 Google 都在用
  • Android 12 行为变更,对应用产生的影响
  • 图解多平台 AndroidStudio 技巧(三)
  • Kotlin StateFlow 搜索功能的实践 DB + NetWork
  • Kotlin 插件的落幕,ViewBinding 的崛起

玻璃钢生产厂家佛山玻璃钢雕塑定制安溪商场美陈制作东莞美陈玻璃钢雕塑云南哪里有玻璃钢卡通雕塑商场美陈摆件汉中玻璃钢商场美陈十堰玻璃钢造型雕塑玻璃钢西瓜雕塑收费焦作抽象玻璃钢仿铜雕塑定做景区玻璃钢雕塑设计制作新兴玻璃钢雕塑常用玻璃钢花盆研发公司广东抽象玻璃钢雕塑生产厂家不锈钢人物玻璃钢雕塑设计江西欧式玻璃钢雕塑市场苏州走廊商场美陈太原玻璃钢传统人物雕塑奉贤区知名玻璃钢雕塑服务介绍福建开业商场美陈厂家直销宁夏大型玻璃钢雕塑设计梅州玻璃钢动物雕塑推荐货源城市玻璃钢雕塑厂家山东玻璃钢花盆生产厂家芒市玻璃钢雕塑多少钱杞县玻璃钢雕塑定制长春玻璃钢雕塑老年宝山区大型玻璃钢雕塑厂家直供树脂玻璃钢雕塑设计公司陕西玻璃钢艺术雕塑性能优良玻璃钢雕塑厂家择优推荐香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化