foreword

Collection source code analysis series: Java collection source code analysis

I have already Vector , ArrayList , LinkedList , I wanted to start Map , but I saw the following interface design framework: The entire interface framework relationship is as follows (from Baidu Encyclopedia):

It turns out that there is another fish that Stack through the net. The 061e3c980a7936 stack is hanging under Vector . We have already analyzed Vector before, so let Stack analyze 061e3c980a793c by the way. It's 2022 if you don't write:

Introduction to Stack

Stack is a data structure, not Java unique in Java reflected inside Stack class. Its essence is first-in, last-out, like a bucket, which can only be placed on it continuously, and when it is taken out, only the top data can be continuously taken out. If you want to take out the data at the bottom, you can only do it when the data above is taken out. Of course, if there is such a need, we generally use a two-way queue.

The following is a demonstration of the characteristics of the stack:

Stack in Java is inherited from the Vector , said here is 1.8 version, the common Vector underlying data structure, the bottom layer are implemented using an array, having the following features:

  • `FILO ( 061e3c980a7aee )
  • Inherited from Vector , also based on array implementation
  • Since almost all Vector are used, Vector are thread-safe, so the Stack are also thread-safe.

Class definition source code:

public
class Stack<E> extends Vector<E> {
}

Member variables have only one serialized variable:

    private static final long serialVersionUID = 1224463164541339165L;

method interpretation

Stack does not have many of its own methods, almost all of which are inherited from Vector . We can look at the 5 methods it has expanded by itself:

  • E push(E item) : push stack
  • synchronized E pop() : pop
  • synchronized E peek() : Get the top element of the stack
  • boolean empty() : Determine if the stack is empty
  • int search(Object o) : Search the index position of an object in the stack

push method

The bottom layer actually calls the addElement() method, which is the Vector method:

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

        return item;
    }

We have analyzed Vecor before, if you are interested, please refer to: http://aphysia.cn/archives/java-ji-he-11vector-chao-ji-xiang-xi-yuan-ma-jie-xi

addElement is thread-safe. It actually adds an element to the back of the array at the bottom layer, but it helps us ensure the capacity. If the capacity is insufficient, the automatic expansion mechanism will be triggered.

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

pop method

The bottom layer is to first call the peek() method to get the top element of the stack, and then call the removeElementAt() method to remove the top element of the stack to achieve the effect of popping the stack.

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

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

        return obj;
    }

removeElementAt(int index) also Vector way, synchronized modification is thread-safe, due to the removal of the last element of an array, so here will not trigger replication element, which is System.arraycopy(elementData, index + 1, elementData, index, j); :

    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 */
    }

peek method

To get the top element of the stack, first get the size of the array, and then call Vector of E elementAt(int index) get the element of the index:

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

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

E elementAt(int index) is as follows, the logic inside is relatively simple, only the judgment of the array out of bounds:

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

        return elementData(index);
    }

empty method

It is mainly used to judge empty, to judge whether there are elements in the element stack, the main call is the size() method:

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

This size() method is actually Vector , and it returns a class variable with the number of elements:

    public synchronized int size() {
        return elementCount;
    }

search method

This method is mainly used to query the index of an element. If there are more than one, it will return the index of the last element:


   public synchronized int search(Object o) {
        int i = lastIndexOf(o);

        if (i >= 0) {
            return size() - i;
        }
        return -1;
    }

Using synchronized decoration is also thread-safe. Why do you need this method?

We know that the stack is first-in, first-out. If you need to find the position of an element in it, you need to take it out one by one and then judge it, it will be too troublesome, and the bottom layer uses an array for storage, you can directly use this feature, you can quickly Find the index position of the element.

So far, looking back, will you be wondering, `Stack , but the data is constantly being manipulated, thanks to the data structure of Vector

        // 底层数组
    protected Object[] elementData;

    // 元素数量
    protected int elementCount;

The bottom layer uses an array to save the number of elements, so the operation element is actually just constantly inserting elements into the array, or taking out the last element.

Summarize

Because stack Vector , it is also thread-safe. The bottom layer uses arrays to save data. Most API use Vector to save data. Its most important property is FIFO. As for the expansion of the array, the expansion logic Vector

If we let us implement it ourselves, the bottom layer does not necessarily use an array, and a linked list can also achieve the same function, but in the entire collection source code system, there are the same parts, which is a good choice.

【About the author】 :
Qin Huai, [ 161e3c980a8548 Qin Huai Grocery Store ], personal website: http://aphysia.cn .

Offer All Solutions PDF

Open Source Programming Notes


秦怀杂货店
147 声望38 粉丝

山高水长,纵使缓慢,驰而不息。