【集合类分析】Stack

来源:互联网 发布:网络宣传计划书范文 编辑:程序博客网 时间:2024/05/29 03:02

官方介绍:
继承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;    }    
原创粉丝点击