PerKins Zhu

Le vent se lève,il faut tenter de vivre.

导航

源码解读—Stack

Posted on 2016-08-19 10:29  PerKins.Zhu  阅读(242)  评论(0编辑  收藏  举报

Stack特性:先进后出、后进先出

java.util.Stack实现了这一数据结构。

   public  class Stack<E> extends Vector<E>,Stack继承Vector,Stack中的所有操作都是调用Vector中的方法进行操作,即使是数据的存储也是使用vector中的Object[] elementData对象数组来进行数据存储的。所以说stack是基于数组的数据结构。

Stack的实现比较简单,一个也就六个方法:

Stack()构造方法:

new Stack()的时候调用空的构造方法。

由于Stack继承了vector,程序继续调用Vector的构造器:Vector();

this(10),继续找到  public Vector(int initialCapacity),可见initialCapacity=10,也即是初始化Object [] elementData数组大小为10

继续执行    this(initialCapacity, 0);找到 public Vector(int initialCapacity, int capacityIncrement) ;capacityIncrement=0;初始化的时候不要进行扩容。

stack 对象创建完成。

public E push(E item):

 程序调用继承自Vector的public synchronized void addElement(E obj);方法添加数据元素。

 

 不明白为什么直接return item而不返回一个操作结果失败成功提示。

进行插入数据操作:

 public synchronized void addElement(E obj) {
                modCount++;//这个来自于Vector的父类AbstractList,不知道是干嘛的
                //elementCount:插入数据所在的数组下标;如果需要,进行数组扩容    
                ensureCapacityHelper(elementCount + 1);
                //把数据保存在数组中
                elementData[elementCount++] = obj;
                }

 

 再看private void ensureCapacityHelper(int minCapacity);

  private void ensureCapacityHelper(int minCapacity) {
        //保存数组长度
    int oldCapacity = elementData.length;
    //如果最小容量大于数组容量则进行扩容操作
    if (minCapacity > oldCapacity) {
        //保存数组数据
        Object[] oldData = elementData;
        //初始化设置的capacityIncrement如果大于0 则新数组容量为原容量+扩容容量,否则2倍扩容
        int newCapacity = (capacityIncrement > 0) ?(oldCapacity + capacityIncrement) : (oldCapacity * 2);
        //如果容量依旧小于最小需要的容量则直接以最小需要容量为扩容后容量
        if (newCapacity < minCapacity) {
            newCapacity = minCapacity;
        }
        //调用Arrays.copyOf赋值新数组
            elementData = Arrays.copyOf(elementData, newCapacity);
    }
    }

 

 再看public synchronized E pop();

    public synchronized E pop() {
    E    obj;
    //获取数组插入数据的个数elementCount(不是数组的长度)
    int    len = size();
    //找到最后插入的元素,进行返回
    obj = peek();
    //删除最后一个元素
    removeElementAt(len - 1);
    return obj;
    }

 

再看public synchronized E peek();
//注意synchronized public synchronized int size() { //获取数组插入数据的个数 return elementCount; } //注意synchronized public synchronized E peek() { int len = size(); if (len == 0) throw new EmptyStackException(); //返回最后一个存储的数据 return elementAt(len - 1); }

 

 public boolean empty() ,判断数组内容数据是否为空,为什么不用 isEmpty()命名呢?……

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

 

public synchronized int search(Object o); 查找数据所处数组位置,如果没有则返回-1

   public synchronized int search(Object o) {
        //获取o所在数组中的最后一个位置。注意这个i是从后向前查的位置,也就是从后向前查,第一个O处于第几个元素
        int i = lastIndexOf(o);
        if (i >= 0) {
            //返回元素所在数组中的位置
            return size() - i;
        }
        return -1;
        }

 

再看lastIndex();

   //调用Vectort的方法
    public synchronized int lastIndexOf(Object o) {
        return lastIndexOf(o, elementCount - 1);
    }
    //注意index传过来的数值
    public synchronized int lastIndexOf(Object o, int index) {
        if (index >= elementCount)
            throw new IndexOutOfBoundsException(index + " >= " + elementCount);
        //由此可见,数组中是可以存储null值的
        if (o == null) {
            //由后向前循环找出元素所在位置
            for (int i = index; i >= 0; i--)
                if (elementData[i] == null)
                    return i;
        } else {
            //由后向前循环找出元素所在位置
            for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        //找不到数据则返回-1
        return -1;
    }

 

Stack本身比较简单,没有太过复杂的操作。