点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~


今天心情不错,再来一篇 Stack !

数据结构中的 栈

数据结构中,栈是一种线性数据结构,遵从 LIFO(后进先出)的操作顺序,所有操作都是在顶部进行

有点像羽毛球筒:

栈通常有三种操作:

  • push 入栈
  • pop 栈顶元素出栈,并返回
  • peek 获取栈顶元素,并不删除

我们自定义一个 栈 时只要实现上述三个主要操作即可,本文中将使用 Java 中的 LinkedList 实现一个栈。

栈的使用场景:

栈最主要的意义就在于:入栈和出栈的对称性。

在 Android 开发中,我们经常需要开启、回退一个 Activity,其实这里就有栈的应用,每次开启Activity,如果不是特殊的启动模式,就会在栈顶加入一个 Activity,点击返回后,之前的 Activity 出栈 。

其他场景比如递归(斐波那契数列,汉诺塔)。

Java 集合框架中的栈 Stack

Java 集合框架中的 Stack 继承自 Vector

  • 由于 Vector 有 4 个构造函数,加上 Stack 本身的一种,也就是说有 5 中创建 Stack 的方法
  • 跟 Vector 一样,它是 数组实现的栈

Stack 的方法

Stack 中新建的方法比较少:

1.构造函数

//构建一个空栈
public Stack() {
}

2.入栈

//调用的 Vector.addElement()
public E push(E item) {
addElement(item); return item;
}

Vector 的 addElement() 方法,就是在数组尾部添加元素:

public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}

3.获取顶端元素,但不删除

public synchronized E peek() {
//调用 Vector.size() 返回元素个数
int len = size(); if (len == 0)
throw new EmptyStackException();
//调用 Vector.elementAt 得到栈顶元素
return elementAt(len - 1);
}

Vector.elementAt(int):

public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
} return elementData(index);
}

Vector.elementData(int):

E elementData(int index) {
return (E) elementData[index];
}

4.出栈

public synchronized E pop() {
E obj;
int len = size(); //调用 peek() 获取顶端元素,一会儿返回
obj = peek();
//调用 Vector.removeElementAt 删除顶端元素
removeElementAt(len - 1); return obj;
}

Vector.removeElementAt(int):

public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
} int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}

5.查找元素是否在栈中

public synchronized int search(Object o) {
int i = lastIndexOf(o); //返回的是栈顶到该元素出现的位置的距离
if (i >= 0) {
return size() - i;
}
return -1;
}

6.是否为空

public boolean empty() {
return size() == 0;
}

Vector.size():

public synchronized int size() {
return elementCount;
}

总结

Java 集合框架中的 Stack 具有以下特点:

  • 继承自 Vector
  • 有 5 种创建 Stack 的方法
  • 采用数组实现
  • 除了 push(),剩下的方法都是同步的

用链表实现一个栈?

由于 Stack 是用数组实现的,我们用链表实现一下吧,这里就选择 LinkedList 来实现:

/**
* description:LinkedList 模拟 Stack
* <br/>
* author: shixinzhang
* <br/>
* data: 10/23/2016
*/
public class LinkedListStack extends LinkedList{
public LinkedListStack(){
super();
} @Override
public void push(Object o) {
super.push(o);
} @Override
public Object pop() {
return super.pop();
} @Override
public Object peek() {
return super.peek();
} @Override
public boolean isEmpty() {
return super.isEmpty();
} public int search(Object o){
return indexOf(o);
}
}

调用:

@Test
public void testPush() throws Exception {
LinkedListStack stack = new LinkedListStack();
System.out.println("栈是否为空: " + stack.isEmpty()); stack.push("shixin");
stack.push("好帅");
stack.push("技巧一流");
stack.push("haha"); System.out.println("栈中元素: " + stack); System.out.println("获取顶端元素 peek :" + stack.peek()); System.out.println("顶端元素出栈 pop :" + stack.pop()); System.out.println("出栈后栈内元素:" + stack); System.out.println("search(好帅) 的位置:" + stack.search("好帅"));
}
}

结果:

可以看到,我其实都没做什么哈哈,都是 LinkedList 内部提供的方法,操作的都是在链表头部的元素,而不是尾部。

其实 LinkedList 这个栈的特性也是继承自 双端队列 Deque,官方也推荐在使用栈时优先使用 Deque,而不是 Stack,有兴趣的可以去了解下。

Thanks

https://docs.oracle.com/javase/8/docs/api/java/util/Stack.html

http://www.cnblogs.com/kaituorensheng/archive/2013/03/02/2939690.html

http://www.nowamagic.net/librarys/veda/detail/2298

Java 集合深入理解(13):Stack 栈的更多相关文章

  1. Java 集合深入理解(8):AbstractSequentialList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天有点无聊,来学学 AbstractSequentialList 解解闷 吧! AbstractSequentialLi ...

  2. Java 集合深入理解(7):ArrayList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情有点美丽,学学 ArrayList 放松下吧! 什么是 ArrayList ArrayList 是 Java 集合 ...

  3. Java 集合深入理解(4):List<E> 接口

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 蓝瘦!香菇! 连着加班几天,醉了.学学 List 放松下! 在 Java 集合深入理解:Collection 中我们熟悉了 ...

  4. Java 集合系列07之 Stack详细介绍(源码解析)和使用示例

    概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...

  5. Java 集合深入理解(12):古老的 Vector

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天刮台风,躲屋里看看 Vector ! 都说 Vector 是线程安全的 ArrayList,今天来根据源码看看是不是这 ...

  6. Java 集合深入理解(11):LinkedList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情鱼肚白,来学学 LinkedList 吧! 日常开发中,保存一组数据使用的最多的就是 ArrayList, 其次就 ...

  7. Java 集合深入理解(10):Deque 双端队列

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 什么是 Deque Deque 是 Double ended queue (双端队列) 的缩写,读音和 deck 一样,蛋 ...

  8. Java 集合深入理解(9):Queue 队列

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情不太好,来学一下 List 吧! 什么是队列 队列是数据结构中比较重要的一种类型,它支持 FIFO,尾部添加.头部 ...

  9. Java 集合深入理解(6):AbstractList

    点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情比天蓝,来学学 AbstractList 吧! 什么是 AbstractList AbstractList 继承自 ...

随机推荐

  1. 怎么实现form表单提交后不重新刷新当前页面

    怎么实现表单提交后不重新刷新当前页面     如何实现表单提交后不重新刷新当前页面 <form name='form1' id='form1' action='/xbcw/cw/xx_xx.ac ...

  2. Play framework logging设置

    play的logger是基于Log4j,Play 2.0 uses logback as its logging engine. 一.配置 1. 在conf/application.conf中设置lo ...

  3. Objective-C(面向对象的三大特性)

    封装 set方法 作用:提供一个方法给外界设置成员变量值,可以在方法里面进行过滤 命名规范 1. 方法名必须以set开头 2. set后面跟上成员变量的名称,成员变量的首字母必须大写 3. 返回值一定 ...

  4. TCP协议基础

    IP协议是Internet上使用的一个关键协议,它的全称是Internet  Protocol,即Internet协议,通常简称IP协议.通过使用IP协议,使Internet·成为一个允许连接不同类型 ...

  5. 近期C++编译问题汇总

    编译c++ 代码中遇到几个问题,汇总一下: 1.编译openssl 遇到问题如图 ,  原因:不支持汇编编译,在perl编译指令中加入: no-asm , 如:perl Configure VC-WI ...

  6. NOIP 2013 提高组 day1 T2 火柴排队 归并 逆序对

    描述 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度.现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:∑i=1n(ai−bi)2∑i=1n(ai−bi) ...

  7. RM报表的选项 注册表位置

    HKCU\Software\WHF SoftWare\Report Machine\RMReport\Form\RMDesignerForm\ 设计器-工具-选项的设置 HKCU\Software\W ...

  8. C++-多重继承的注意点

    1, 钻石型多重继承如果不想要底部的类有重复的变量,则需要声明为virtual继承 class File{...}; class InputFile: virtual public File{..}; ...

  9. Ubuntu13.04 配置smb服务器-new

    1.安装smb服务器:apt-get install samba 2.安装smb支持的文件系统:apt-get install smbfs 或者cifs-utils(因为可能会提示smbfs以过期,已 ...

  10. 修改Azure Website 移动服务 默认时区

    Azure Website 默认时区为国际标准时间,对中国用户来说不太方便友好,如何设置成北京时间呢? 打开Azure Website的“配置”页,找到“应用设置”节点. 在应用设置中添加设置项,密钥 ...