JDK source code analysis -Vector

Outline


Above " JDK source code analysis -ArrayList " analyzes the realization of the principle of ArrayList. This paper analyzes another class that implements the List interface: Vector.


Vector implementation and internal ArrayList similar, can also be understood as a "variable array." Which follows the inheritance structure (not part of the interface):


PS: As the Vector currently use less, and the government has also recommended ArrayList instead of Vector in the process of wireless security requirements, just to study its implementation principle.


stackoverflow also related to the discussion:

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


Still be analyzed from the constructor to start.



Constructor


Vector Foreign offers four constructors (interior can be considered two), one:

protected Object[] elementData;

protected int capacityIncrement;

// 无参构造器
public Vector() {
    this(10);
}

// 指定容量的构造器
public Vector(int initialCapacity) {
    this(initialCapacity, 0);
}

// 指定初始容量和容量增长因子的构造器
public Vector(int initialCapacity, int capacityIncrement) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];
    this.capacityIncrement = capacityIncrement;
}        


与 ArrayList 类似,Vector 内部也维护了一个 Object 类型的数组(elementData)来存储元素(默认初始容量也是 10)。不同的是:Vector 比 ArrayList 的构造器多了一个参数 capacityIncrement,该变量也导致了二者的扩容方式略有不同,后面进行分析。


其二:入参为集合的构造器

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);
}       



扩容原理分析


我们仍从其 add() 方法入手进行分析:

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


注意这里的关键字 synchronized。观察可以发现:Vector 内部许多方法都使用了该关键字,这也是 Vector 实现线程安全的方式,简单粗暴!


其扩容方法实现如下:

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

protected int elementCount;

/*
 * 该方法是非同步的
 * 因为 Vector 内部调用该方法的地方都使用了 synchronized 关键字进行同步,这里不再额外使用
 */

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);
    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;
}                


从这里可以看出,Vector 与 ArrayList 的扩容方式基本一致,只是新容量的计算方式有所不同,这里分析下其新容量大小:

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


Vector 计算扩容后的新容量时,根据 capacityIncrement 的值可以分为两种情况:


1. capacityIncrement > 0:新容量 = 旧容量 + capacityIncrement;


2. capacityIncrement <= 0:新容量 = 旧容量 * 2。



线程安全性


Vector 是线程安全的,它实现线程安全的方式也很简单粗暴:直接在方法上使用 synchronized 关键字进行同步。



Vector 小结


1. 与 ArrayList 类似,Vector 也可以认为是「可变数组」;


2. 扩容原理与 ArrayList 基本一致,只是新容量计算方式略有不同:指定增长容量时,新容量为旧容量 + 增长容量;否则扩容为旧容量的 2 倍;


3. 线程安全的,实现方式简单(synchronized);


4. 当前使用较少,这里仅学习其实现原理。



Stay hungry, stay foolish.

Guess you like

Origin juejin.im/post/5d4fe3d0e51d453c11684c28