Introduction of the Vector

The basic structure of ArrayList and Vector are similar, but they differ in some details: whether they are thread-safe or not, the size of expansion, etc. The thread-safe of Vector is realized by directly adding synchronized to its methods. By default, the capacity expansion is twice the original capacity.

Inheritance system

Vector extends AbstractList and implements List, RandomAccess, Cloneable, Serializable interfaces. Therefore, Vector supports fast RandomAccess, cloning, and serialization.

Vector member variables (attributes)

// Array of type Object
// Note that access modifiers are different: Vector is protected and ArrayList is private.
// In JavaSe: Private variables can only be accessed by methods of the current class, while protected can be accessed by all classes in the same package and subclasses of other packages
protected Object[] elementData;

// The actual effective size of the dynamic array, i.e. the number of elements stored in the array
protected int elementCount;
    
// The growth coefficient of the dynamic array: if the start is not specified, the default is to double the size
protected int capacityIncrement;
   
// Sequence version number
private static final long serialVersionUID = -2767605614048989439L;
Copy the code

Vector constructor

We have four constructors for Vector:

// Default null parameter constructor
public Vector(a) {
    // Call the constructor that specifies an initial capacity of 10
    this(10);
}

// Can specify the initial capacity constructor
public Vector(int initialCapacity) {
    // Call the constructor that specifies the initial capacity and the growth factor, which is set to 0
    this(initialCapacity, 0);
}

// Can specify the initial capacity and growth factor constructor
public Vector(int initialCapacity, int capacityIncrement) {
    super(a);if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    // Create an array of type Object based on the initial capacity
    this.elementData = new Object[initialCapacity];
    // Assign a value to the growth coefficient
    this.capacityIncrement = capacityIncrement;
}

// A constructor that takes a collection type
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)// Copy the data in parameter set C to elementData
        elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}
Copy the code

Vector member methods

The get method

// Get the element data with the specified index
public synchronized E get(int index) {
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    return elementData(index);
}

@SuppressWarnings("unchecked")
E elementData(int index) {
    return (E) elementData[index];
}
Copy the code

Set method

// Modifies the element data with the specified subscript
public synchronized E set(int index, E element) {
    if (index >= elementCount)
        throw new ArrayIndexOutOfBoundsException(index);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}
Copy the code

The remove method

// Delete some element data
public boolean remove(Object o) {
    return removeElement(o);
}

// 
public synchronized boolean removeElement(Object obj) {
    modCount++;
    // Find the subscript of the specified element
    int i = indexOf(obj);
    if (i >= 0) {
        // Delete elements according to the subscript
        removeElementAt(i);
        return true;
    }
    return false;
}

// Delete elements according to the subscript
public synchronized void removeElementAt(int index) {
    modCount++;
    if (index >= elementCount) {
        throw new ArrayIndexOutOfBoundsException(index + "> =" +
                                                 elementCount);
    }
    else if (index < 0) {
        throw new ArrayIndexOutOfBoundsException(index);
    }
    // The number of valid elements after index
    int j = elementCount - index - 1;
    if (j > 0) {
        // Replace the old array with the new array
        System.arraycopy(elementData, index + 1, elementData, index, j);
    }
    // Number of valid elements --
    elementCount--;
    elementData[elementCount] = null; /* to let gc do its work */
}
Copy the code

The add method

// Adds the specified element to the end of the array
public synchronized boolean add(E e) {
    modCount++;
    // Determine whether capacity expansion is required
    ensureCapacityHelper(elementCount + 1);
    elementData[elementCount++] = e;
    return true;
}
Copy the code

Other methods

// Copy all elements in the array Vector into anArray, calling arrayCopy
public synchronized void copyInto(Object[] anArray) {
    System.arraycopy(elementData, 0, anArray, 0, elementCount);
}

public synchronized void trimToSize(a) {
    modCount++;
    int oldCapacity = elementData.length;
    if(elementCount < oldCapacity) { elementData = Arrays.copyOf(elementData, elementCount); }}// Set the size of the Vector
public synchronized void setSize(int newSize) {
    // Number of changes ++
    modCount++;
    // Determine whether the array size is greater than the number of valid elements stored in the Vector
    // If newSize > Vector has the number of valid elements to store, adjust the size of the Vector
    if (newSize > elementCount) {
        // Call the method to determine whether to expand the capacity, if necessary, the method calls the expansion method grow()
        ensureCapacityHelper(newSize);
    } else {
        // If the above judgment is not true, set all elements after the newSize position to NULL
        for (int i = newSize ; i < elementCount ; i++) {
            elementData[i] = null; }}// Update the number of valid elements
    elementCount = newSize;
}

// Get the current capacity of Vector
public synchronized int capacity(a) {
    return elementData.length;
}

// Get the number of valid elements in the Vector
public synchronized int size(a) {
    return elementCount;
}

// Check whether Vecotor contains element O
public boolean contains(Object o) {
    return indexOf(o, 0) > =0;
}

// Get the index of o in the Vector for the first occurrence, or -1 if it does not exist
public int indexOf(Object o) {
    return indexOf(o, 0);
}

// Returns the index of the first occurrence of the object o from index, or -1 if none exists
public synchronized int indexOf(Object o, int index) {
    if (o == null) {
        for (int i = index ; i < elementCount ; i++)
            if (elementData[i]==null)
                return i;
    } else {
        for (int i = index ; i < elementCount ; i++)
            if (o.equals(elementData[i]))
                return i;
    }
    return -1; }...Copy the code

Vector capacity expansion method

// Determine the current capacity of the array
public synchronized void ensureCapacity(int minCapacity) {
    if (minCapacity > 0) { modCount++; ensureCapacityHelper(minCapacity); }}// If the current capacity is greater than the current array length, call grow(minCapacity) to expand the array size
// Since this method is called in ensureCapacity(), which already has a synchronized lock attached to it, synchronized locks can be synchronized
// This method does not need to be locked
private void ensureCapacityHelper(int minCapacity) {
    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// The maximum size of the array
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE 
    
// Core expansion methods in the Vector collection
private void grow(int minCapacity) {
    // overflow-conscious code
    // Get the capacity of the old array
    int oldCapacity = elementData.length;
    // Get the new array capacity after expansion (if needed)
    int newCapacity = oldCapacity + ((capacityIncrement > 0)? capacityIncrement : oldCapacity);// if the newCapacity is less than the actual capacity of the array, newCapacity = minCapacity
    if (newCapacity - minCapacity < 0)
         newCapacity = minCapacity;
    // If the current required capacity > MAX_ARRAY_SIZE, set the new capacity to integer. MAX_VALUE, otherwise set it to MAX_ARRAY_SIZE
    if (newCapacity - MAX_ARRAY_SIZE > 0)
         newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}
         
// Maximum capacity
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}
Copy the code

Complete source code

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess.Cloneable.java.io.Serializable
{
 
    protected Object[] elementData;

    protected int elementCount;
    
    protected int capacityIncrement;
    
    private static final long serialVersionUID = -2767605614048989439L;

    public Vector(int initialCapacity, int capacityIncrement) {
        super(a);if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }

    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }

    public Vector(a) {
        this(10);
    }
   
    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); }public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }

    public synchronized void trimToSize(a) {
        modCount++;
        int oldCapacity = elementData.length;
        if(elementCount < oldCapacity) { elementData = Arrays.copyOf(elementData, elementCount); }}public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) { modCount++; ensureCapacityHelper(minCapacity); }}private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

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

    public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementCount) {
            ensureCapacityHelper(newSize);
        } else {
            for (int i = newSize ; i < elementCount ; i++) {
                elementData[i] = null;
            }
        }
        elementCount = newSize;
    }

    public synchronized int capacity(a) {
        return elementData.length;
    }

    public synchronized int size(a) {
        return elementCount;
    }

    public synchronized boolean isEmpty(a) {
        return elementCount == 0;
    }

    public Enumeration<E> elements(a) {
        return new Enumeration<E>() {
            int count = 0;

            public boolean hasMoreElements(a) {
                return count < elementCount;
            }

            public E nextElement(a) {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        returnelementData(count++); }}throw new NoSuchElementException("Vector Enumeration"); }}; }public boolean contains(Object o) {
        return indexOf(o, 0) > =0;
    }

    public int indexOf(Object o) {
        return indexOf(o, 0);
    }

    public synchronized int indexOf(Object o, int index) {
        if (o == null) {
            for (int i = index ; i < elementCount ; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index ; i < elementCount ; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

    public synchronized int lastIndexOf(Object o) {
        return lastIndexOf(o, elementCount-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--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

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

        return elementData(index);
    }

    public synchronized E firstElement(a) {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(0);
    }

    public synchronized E lastElement(a) {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(elementCount - 1);
    }

    public synchronized void setElementAt(E obj, int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + "> =" +
                                                     elementCount);
        }
        elementData[index] = obj;
    }

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

    public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + ">" + elementCount);
        }
        ensureCapacityHelper(elementCount + 1);
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }

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

    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }

    public synchronized void removeAllElements(a) {
        modCount++;
        // Let gc do its work
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;

        elementCount = 0;
    }

    public synchronized Object clone(a) {
        try {
            @SuppressWarnings("unchecked")
                Vector<E> v = (Vector<E>) super.clone();
            v.elementData = Arrays.copyOf(elementData, elementCount);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw newInternalError(e); }}public synchronized Object[] toArray() {
        return Arrays.copyOf(elementData, elementCount);
    }

    @SuppressWarnings("unchecked")
    public synchronized <T> T[] toArray(T[] a) {
        if (a.length < elementCount)
            return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

        System.arraycopy(elementData, 0, a, 0, elementCount);

        if (a.length > elementCount)
            a[elementCount] = null;

        return a;
    }

    // Positional Access Operations

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }

    public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

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

    public boolean remove(Object o) {
        return removeElement(o);
    }

    public void add(int index, E element) {
        insertElementAt(element, index);
    }

    public synchronized E remove(int index) {
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index);

        int numMoved = elementCount - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--elementCount] = null; // Let gc do its work

        return oldValue;
    }

    public void clear(a) {
        removeAllElements();
    }

    // Bulk Operations

    public synchronized boolean containsAll(Collection
        c) {
        return super.containsAll(c);
    }

    public synchronized boolean addAll(Collection<? extends E> c) {
        modCount++;
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);
        System.arraycopy(a, 0, elementData, elementCount, numNew);
        elementCount += numNew;
        returnnumNew ! =0;
    }

    public synchronized boolean removeAll(Collection
        c) {
        return super.removeAll(c);
    }

    public synchronized boolean retainAll(Collection
        c) {
        return super.retainAll(c);
    }

    public synchronized boolean addAll(int index, Collection<? extends E> c) {
        modCount++;
        if (index < 0 || index > elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);

        int numMoved = elementCount - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        elementCount += numNew;
        returnnumNew ! =0;
    }

    public synchronized boolean equals(Object o) {
        return super.equals(o);
    }

    public synchronized int hashCode(a) {
        return super.hashCode();
    }

    public synchronized String toString(a) {
        return super.toString();
    }

    public synchronized List<E> subList(int fromIndex, int toIndex) {
        return Collections.synchronizedList(super.subList(fromIndex, toIndex),
                                            this);
    }

    protected synchronized void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = elementCount - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // Let gc do its work
        int newElementCount = elementCount - (toIndex-fromIndex);
        while(elementCount ! = newElementCount) elementData[--elementCount] =null;
    }

    private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField gfields = in.readFields();
        int count = gfields.get("elementCount".0);
        Object[] data = (Object[])gfields.get("elementData".null);
        if (count < 0 || data == null || count > data.length) {
            throw new StreamCorruptedException("Inconsistent vector internals");
        }
        elementCount = count;
        elementData = data.clone();
    }

    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
        final java.io.ObjectOutputStream.PutField fields = s.putFields();
        final Object[] data;
        synchronized (this) {
            fields.put("capacityIncrement", capacityIncrement);
            fields.put("elementCount", elementCount);
            data = elementData.clone();
        }
        fields.put("elementData", data);
        s.writeFields();
    }

    public synchronized ListIterator<E> listIterator(int index) {
        if (index < 0 || index > elementCount)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }

    public synchronized ListIterator<E> listIterator(a) {
        return new ListItr(0);
    }

    public synchronized Iterator<E> iterator(a) {
        return new Itr();
    }

    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext(a) {
            // Racy but within spec, since modifications are checked
            // within or after synchronization in next/previous
            returncursor ! = elementCount; }public E next(a) {
            synchronized (Vector.this) {
                checkForComodification();
                int i = cursor;
                if (i >= elementCount)
                    throw new NoSuchElementException();
                cursor = i + 1;
                returnelementData(lastRet = i); }}public void remove(a) {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.remove(lastRet);
                expectedModCount = modCount;
            }
            cursor = lastRet;
            lastRet = -1;
        }

        @Override
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            synchronized (Vector.this) {
                final int size = elementCount;
                int i = cursor;
                if (i >= size) {
                    return;
                }
        @SuppressWarnings("unchecked")
                final E[] elementData = (E[]) Vector.this.elementData;
                if (i >= elementData.length) {
                    throw new ConcurrentModificationException();
                }
                while(i ! = size && modCount == expectedModCount) { action.accept(elementData[i++]); }// update once at end of iteration to reduce heap write traffic
                cursor = i;
                lastRet = i - 1; checkForComodification(); }}final void checkForComodification(a) {
            if(modCount ! = expectedModCount)throw newConcurrentModificationException(); }}/** * An optimized version of AbstractList.ListItr */
    final class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super(a); cursor = index; }public boolean hasPrevious(a) {
            returncursor ! =0;
        }

        public int nextIndex(a) {
            return cursor;
        }

        public int previousIndex(a) {
            return cursor - 1;
        }

        public E previous(a) {
            synchronized (Vector.this) {
                checkForComodification();
                int i = cursor - 1;
                if (i < 0)
                    throw new NoSuchElementException();
                cursor = i;
                returnelementData(lastRet = i); }}public void set(E e) {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.set(lastRet, e); }}public void add(E e) {
            int i = cursor;
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.add(i, e);
                expectedModCount = modCount;
            }
            cursor = i + 1;
            lastRet = -1; }}@Override
    public synchronized void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int elementCount = this.elementCount;
        for (int i=0; modCount == expectedModCount && i < elementCount; i++) {
            action.accept(elementData[i]);
        }
        if(modCount ! = expectedModCount) {throw newConcurrentModificationException(); }}@Override
    @SuppressWarnings("unchecked")
    public synchronized boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        // figure out which elements are to be removed
        // any exception thrown from the filter predicate at this stage
        // will leave the collection unmodified
        int removeCount = 0;
        final int size = elementCount;
        final BitSet removeSet = new BitSet(size);
        final int expectedModCount = modCount;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            @SuppressWarnings("unchecked")
            final E element = (E) elementData[i];
            if(filter.test(element)) { removeSet.set(i); removeCount++; }}if(modCount ! = expectedModCount) {throw new ConcurrentModificationException();
        }

        // shift surviving elements left over the spaces left by removed elements
        final boolean anyToRemove = removeCount > 0;
        if (anyToRemove) {
            final int newSize = size - removeCount;
            for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
                i = removeSet.nextClearBit(i);
                elementData[j] = elementData[i];
            }
            for (int k=newSize; k < size; k++) {
                elementData[k] = null;  // Let gc do its work
            }
            elementCount = newSize;
            if(modCount ! = expectedModCount) {throw new ConcurrentModificationException();
            }
            modCount++;
        }

        return anyToRemove;
    }

    @Override
    @SuppressWarnings("unchecked")
    public synchronized void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final int size = elementCount;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            elementData[i] = operator.apply((E) elementData[i]);
        }
        if(modCount ! = expectedModCount) {throw new ConcurrentModificationException();
        }
        modCount++;
    }

    @SuppressWarnings("unchecked")
    @Override
    public synchronized void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, elementCount, c);
        if(modCount ! = expectedModCount) {throw new ConcurrentModificationException();
        }
        modCount++;
    }

    @Override
    public Spliterator<E> spliterator(a) {
        return new VectorSpliterator<>(this.null.0, -1.0);
    }

    /** Similar to ArrayList Spliterator */
    static final class VectorSpliterator<E> implements Spliterator<E> {
        private final Vector<E> list;
        private Object[] array;
        private int index; // current index, modified on advance/split
        private int fence; // -1 until used; then one past last index
        private int expectedModCount; // initialized when fence set

        /** Create new spliterator covering the given range */
        VectorSpliterator(Vector<E> list, Object[] array, int origin, int fence,
                          int expectedModCount) {
            this.list = list;
            this.array = array;
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

        private int getFence(a) { // initialize on first use
            int hi;
            if ((hi = fence) < 0) {
                synchronized(list) { array = list.elementData; expectedModCount = list.modCount; hi = fence = list.elementCount; }}return hi;
        }

        public Spliterator<E> trySplit(a) {
            int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
            return (lo >= mid) ? null :
                new VectorSpliterator<E>(list, array, lo, index = mid,
                                         expectedModCount);
        }

        @SuppressWarnings("unchecked")
        public boolean tryAdvance(Consumer<? super E> action) {
            int i;
            if (action == null)
                throw new NullPointerException();
            if (getFence() > (i = index)) {
                index = i + 1;
                action.accept((E)array[i]);
                if(list.modCount ! = expectedModCount)throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }

        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> action) {
            int i, hi; // hoist accesses and checks from loop
            Vector<E> lst; Object[] a;
            if (action == null)
                throw new NullPointerException();
            if((lst = list) ! =null) {
                if ((hi = fence) < 0) {
                    synchronized(lst) { expectedModCount = lst.modCount; a = array = lst.elementData; hi = fence = lst.elementCount; }}else
                    a = array;
                if(a ! =null && (i = index) >= 0 && (index = hi) <= a.length) {
                    while (i < hi)
                        action.accept((E) a[i++]);
                    if (lst.modCount == expectedModCount)
                        return; }}throw new ConcurrentModificationException();
        }

        public long estimateSize(a) {
            return (long) (getFence() - index);
        }

        public int characteristics(a) {
            returnSpliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; }}}Copy the code