[JDK] JDK Source Analysis-Vector

Keywords: PHP JDK less Java

Summary

 

"Above." JDK Source Analysis-ArrayList This paper mainly analyses the implementation principle of ArrayList. This article analyses another implementation class of the List interface: Vector.

 

Vector's internal implementation is similar to ArrayList and can also be understood as a "variable array". Its inheritance structure is as follows (omitting some interfaces):

PS: Because Vector is currently used less, and it is officially recommended to use ArrayList instead of Vector when there is no thread-safe requirement, this paper only studies its implementation principle.

 

Stack overflow has also been discussed:

https://stackoverflow.com/questions/1386275/why-is-java-vector-and-stack-class-considered-obsolete-or-deprecated

 

It is still analyzed from its constructor.  

 

constructor

 

Vector provides four external constructors (which can be considered as two internally), one of which is:

protected Object[] elementData;

protected int capacityIncrement;

// Parametric constructor
public Vector() {
    this(10);
}

// Constructor with specified capacity
public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

// Constructor specifying initial capacity and capacity growth factor
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
}        

Similar to ArrayList, Vector maintains an Object-type array (elementData) to store elements (the default initial capacity is 10). The difference is that Vector has an additional parameter capacityIncrement than the ArrayList constructor, which also leads to a slightly different way of expanding the two.

 

The second is the constructor that takes part in the set.

public Vector(Collection<? extends E> c) {
    elementData = c.toArray();
    elementCount = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}

 

Analysis of Expansion Principle

 

We still start with its add() method to analyze:

public synchronized boolean add(E e) {
    modCount++;
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}   

Note the keyword synchronized here. Observation can be found: Vector internal many methods have used the keyword, which is also the way Vector thread safety, simple and rough!

 

The expansion method is as follows:

/**
 * The number of valid components in this {@code Vector} object.
 * Components elementData[0] through
 * elementData[elementCount-1] are the actual items.
 */
protected int elementCount;

/*
 * This method is asynchronous.
 * Because synchronized keywords are used for synchronization where Vector calls this method internally, there is no additional use here.
 */
private void ensureCapacityHelper(int minCapacity) {
    // overflow-conscious code
    // Expansion when the capacity of the array is larger than the capacity of the array
    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);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}                

 

From this, we can see that Vector and ArrayList are basically the same way to expand, but the way to calculate the new capacity is different. Here we analyze the size of the new capacity:

int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);

 

When Vector calculates the new capacity after expansion, it can be divided into two cases according to the value of capacityIncrement:

 

1. Capacity Increment > 0: New capacity = Old capacity + Capacity Increment;

 

2. Capacity Increment <= 0: New capacity = Old capacity * 2.

 

Thread security

 

Vector is thread-safe, and the way it implements thread-safe is also simple and crude: synchronized keywords are used directly in the method to synchronize.

 

Vector Summary

 

1. Similar to ArrayList, Vector can also be considered a "variable array";

 

2. The principle of capacity expansion is basically the same as that of ArrayList, except that the new capacity calculation method is slightly different: the new capacity is the old capacity + the growth capacity when the growth capacity is specified; otherwise, the capacity expansion is twice the old capacity;

 

3. Thread-safe, simple to implement (synchronized);

 

4. Currently, it is seldom used. Here we only study its implementation principle.  

 

Stay hungry, stay foolish.

PS: This article was first published on Wechat Public Number.

Posted by pieai on Fri, 28 Jun 2019 13:49:41 -0700