【集合类分析】Stack

官方介绍:
继承Vector类,再加了五个方法,实现了Stack的LIFO


protected Object[] elementData; // 底层数据结构
protected int elementCount; // 有效的元素数量
    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

为什么一开始的最大容量要设为Integer.MAX_VALUE - 8?

是否减8没那么重要(只是为了避免一些机器内存溢出),最大长度依然是Integer.MAX_VALUE,并不是Integer.MAX_VALUE-8,看源码就知道,扩容那里,如果超过了之前设置的最大值,就直接按 Integer.MAX_VALUE处理。

而为什么会有这个最大长度,一是因为记录容器size的数据是一个int类型。


push方法

public E push(E item) {
        addElement(item);

        return item;
    }

public synchronized void addElement(E obj) {
        modCount++; // Stack的修改次数
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }    

push方法中需要确保容量:

private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity); // capacityIncrement在构造Vector函数的时候初始化,否则为0;则(暂定)新容量是旧容量的两倍
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity; // 如果求出来的新容量比需要的容量还要小,则直接将新容量设为所需容量
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity); // 
        elementData = Arrays.copyOf(elementData, newCapacity); // 用了这个方法,来把旧数组的内容放到新数组中,底层调用的是native方法
    }    

pop方法:

    public synchronized E pop() {
        E       obj;
        int     len = size();  // return elementCount

        obj = peek();
        removeElementAt(len - 1);

        return obj;
    }

    public synchronized void removeElementAt(int index) { // 这里调用的是Vector里的方法,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); // 也是一个native方法,但在这里用不到,因为j=0;
            //public static void arraycopy(Object src,int srcPos, Object dest,int destPos,int length)
        }
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }

peek和empty方法都很简单

    public synchronized E peek() {
        int     len = size();

        if (len == 0)
            throw new EmptyStackException();
        return elementAt(len - 1);
    }

search方法:

    public synchronized int search(Object o) {
        int i = lastIndexOf(o); // 因为search是要求离栈顶最近的满足要求的元素,所以正好调用这个方法

        if (i >= 0) {
            return size() - i; // 返回的是离栈顶的距离
        }
        return -1;
    }

    public synchronized int lastIndexOf(Object o, int index) {
        if (index >= elementCount)
            throw new IndexOutOfBoundsException(index + " >= "+ elementCount);

        if (o == null) {
            for (int i = index; i >= 0; i--) // 因为是lastIndex,所以从后往前搜索
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        } // 可以学习一下这里对于null和普通元素的处理
        return -1;
    }    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值