主頁 > 後端開發 > Array原始碼刨析

Array原始碼刨析

2022-07-15 06:37:20 後端開發

目錄
  • @SuppressWarnings
  • Spliterator
  • Fail-Fast
  • 序列化
  • Consumer
  • Vector刨析
  • ArrayList刨析
  • Stack刨析

總結:Java的Stack嚴格意義來說并不能說是Stack,因為它通過直接繼承Vector類,繼承了Vector所有的公有方法,它是一個擁有所有Vector容器方法的堆疊!

@SuppressWarnings

該批注的作用是給編譯器一條指令,告訴它對被批注的代碼元素內部的某些警告保持靜默,

all 抑制所有警告
boxing 抑制裝箱、拆箱操作時候的警告
cast 抑制映射相關的警告
dep-ann 抑制啟用注釋的警告
deprecation 抑制過期方法警告
fallthrough 抑制確在switch中缺失breaks的警告
finally 抑制finally模塊沒有回傳的警告
hiding to suppress warnings relative to locals that hide variable
incomplete-switch 忽略沒有完整的switch陳述句的警告
nls 忽略非nls格式的字符的警告
null 忽略對null的操作的警告
rawtypes 使用generics時忽略沒有指定相應的型別的警告
restriction restriction to suppress warnings relative to usage of discouraged or forbidden references
serial 忽略在serializable類中沒有宣告serialVersionUID變數的警告
static-access 抑制不正確的靜態訪問方式警告
synthetic-access 抑制子類沒有按最優方法訪問內部類的警告
unchecked 抑制沒有進行型別檢查操作的警告
unqualified-field-access 抑制沒有權限訪問的域的警告
unused 抑制沒被使用過的代碼的警告

Spliterator

Spliterator是Java 8中加入的一個新介面;這個名字代表“可拆分迭代器”(splitable iterator),和Iterator一樣,Spliterator也用于遍歷資料源中的元素,但它是為了并行執行而設計的,Java 8已經為集合框架中包含的所有資料結構提供了一個默認的Spliterator實作,

Fail-Fast

fail-fast 機制,即快速失敗機制,是java集合(Collection)中的一種錯誤檢測機制,當在迭代集合的程序中該集合在結構上發生改變的時候,就有可能會發生fail-fast,即拋出 ConcurrentModificationException例外,fail-fast機制并不保證在不同步的修改下一定會拋出例外,它只是盡最大努力去拋出,所以這種機制一般僅用于檢測bug,

Vector中依賴modCount實作,一旦modCount發生變化,那么就觸發例外,

序列化

Java 提供了一種物件序列化的機制,該機制中,一個物件可以被表示為一個位元組序列,該位元組序列包括該物件的資料、有關物件的型別的資訊和存盤在物件中資料的型別,

將序列化物件寫入檔案之后,可以從檔案中讀取出來,并且對它進行反序列化,也就是說,物件的型別資訊、物件的資料,還有物件中的資料型別可以用來在記憶體中新建物件,

Consumer

函式式編程介面

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Vector刨析

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    
    //一個確保足夠大的陣列緩沖區
    @SuppressWarnings("serial") // Conditionally serializable
    protected Object[] elementData;

    //記錄陣列緩沖區中實際存入的元素數量
    protected int elementCount;

    //vector容器建議自增的大小
    protected int capacityIncrement;

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    @java.io.Serial
    private static final long serialVersionUID = -2767605614048989439L;

    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        //首次Vector初始化
        this.elementData = https://www.cnblogs.com/angelMask/p/new Object[initialCapacity];
        //設定下次Vector容量的增加數量
        this.capacityIncrement = capacityIncrement;
    }

    public Vector(int initialCapacity) {
        //若capacityIncrement為空,則默認設定為0,即不會擴大容量
        this(initialCapacity, 0);
    }

    public Vector() {
        //默認Vector僅能存盤十個元素,且不會容量不會擴大!
        this(10);
    }

    //Collection物件賦值給Vector的兩種情況
    public Vector(Collection<? extends E> c) {
        Object[] a = c.toArray();
        elementCount = a.length;
        //如果c的類物件是ArrayList的話,那么就可以直接賦值
        if (c.getClass() == ArrayList.class) {
            elementData = a;
        } else {
        //elementDate賦值為Object[]
            elementData = Arrays.copyOf(a, elementCount, Object[].class);
        }
    }

    /*
    	arraycopy(src, srcPos, dest, destPos, length)
    	1. src: 源陣列
    	2. srcPos: 源陣列的起點下標
    	3. dest: 目標陣列
    	4. destPos: 目標陣列的起點下標
    	5. length: 復制源陣列的元素個數
    */
    //拷貝vector
    public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }

   	//修剪vector
    public synchronized void trimToSize() {
        modCount++;
        int oldCapacity = elementData.length;
        //如果陣列的大小大于陣列中元素的個數,則將陣列容量縮小為元素個數的容量
        if (elementCount < oldCapacity) {
            elementData = Arrays.copyOf(elementData, elementCount);
        }
    }

    /**
     * modCount定義在AbstractList中,用于記錄當前集合嘗試改變容量的次數
     * 設定容器的最小容量
     */
    public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            if (minCapacity > elementData.length)
                grow(minCapacity);
        }
    }

    /**
     * ArraysSupport.newLength(oldLength, minGrowth, prefGrowth)
     * newLength函式中定義了取oldLength + max(minGrowth, prefGrowth)
     * 即grow函式最小也會增長minGrowth, 最大則增加prefGrowth
     * 也就是說一旦呼叫了grow()函式,那么增加的容量并不是設定的minCapacity而是經過的	   * 計算的容量
     */
    private Object[] grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                minCapacity - oldCapacity, //minGrow
                capacityIncrement > 0 ? capacityIncrement : oldCapacity//preGrow
                 );
        return elementData = Arrays.copyOf(elementData, newCapacity);
    }

    //默認自增1
    private Object[] grow() {
        return grow(elementCount + 1);
    }

    //設定vector大小
    //第一種情況,若vector的元素數量小于newSize那么直接擴大容量
    //第二種情況,若vector的元素數量大于newSize那么就將多余的部分置為null,但是不修	 //改vector本身的容量
    public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementData.length)
            grow(newSize);
        final Object[] es = elementData;
        for (int to = elementCount, i = newSize; i < to; i++)
            es[i] = null;
        elementCount = newSize;
    }

    //定義容量=容器大小
    public synchronized int capacity() {
        return elementData.length;
    }

    //定義大小=元素數量
    public synchronized int size() {
        return elementCount;
    }

    //判空
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }

    //獲取列舉物件
    public Enumeration elements() {
        return new Enumeration() {
            //自定義列舉介面
            int count = 0;

            //提供給外部回圈使用的
            public boolean hasMoreElements() {
                return count < elementCount;
            }
			
            //拿到當前元素的值,并將列舉指向下一個
            public E nextElement() {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return elementData(count++);
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }

    //indexOf(Object, x)找到Object則回傳下標,反之,回傳-1
    public boolean contains(Object o) {
        return indexOf(o, 0) >= 0;
    }

    //從零開始找目標Object
    public int indexOf(Object o) {
        return indexOf(o, 0);
    }

    //應該很好理解,為什么需要將NULL物件和Object物件區分?為什么需要使用equals()?
    //equals()中的物件不能為null, ==判別的是地址是否相同而非大小
    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;
    }

   //Object最后一次出現的下標
    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() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(0);
    }

    //獲取最后一位元素
    public synchronized E lastElement() {
        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) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        //拷貝elementData的index+1處往后的元素至elementData的index處往后的元素
        if (j > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        modCount++;
        elementCount--;
        elementData[elementCount] = null; /* 為了讓GC回收null元素 */
    }

    //在特定下標插入元素
    public synchronized void insertElementAt(E obj, int index) {
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        modCount++;
        final int s = elementCount;
        Object[] elementData = https://www.cnblogs.com/angelMask/p/this.elementData;
        //如果容量和元素數量相等,就擴容1
        if (s == elementData.length)
            elementData = grow();
        //拷貝elementData的index往后的元素至elementData的index+1往后的元素
        System.arraycopy(elementData, index,
                         elementData, index + 1,
                         s - index);
        elementData[index] = obj;
        elementCount = s + 1;
    }

    //在vector尾部增加元素
    public synchronized void addElement(E obj) {
        modCount++;
        add(obj, elementData, elementCount);
    }

    //洗掉特定的元素->先找下標位置->洗掉特定下標的元素
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }

    //i=elementCount=0 elementCount=0 -> i=0
    //將所有元素置空,但并未修改容量大小
    public synchronized void removeAllElements() {
        final Object[] es = elementData;
        for (int to = elementCount, i = elementCount = 0; i < to; i++)
            es[i] = null;
        modCount++;
    }

    //手把手教你寫深拷貝
    public synchronized Object clone() {
        try {
            @SuppressWarnings("unchecked")
            Vector<E> v = (Vector<E>) super.clone();
            v.elementData = https://www.cnblogs.com/angelMask/p/Arrays.copyOf(elementData, elementCount);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }

    //也算是深拷貝吧?
    public synchronized Object[] toArray() {
        return Arrays.copyOf(elementData, elementCount);
    }

    //轉換成T[]實際上也是
    @SuppressWarnings("unchecked")
    public synchronized <T> T[] toArray(T[] a) {
        //這里會出問題,因為傳入的陣列太小而無法接收,因此JDK被迫回傳了一個新的陣列
        //那么傳進來的a的所有資料就會為空!
        if (a.length < elementCount)
            return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

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

        //意義是什么?應該和JVM的GC回收有關系,
        if (a.length > elementCount)
            a[elementCount] = null;

        return a;
    }

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

    @SuppressWarnings("unchecked")
    static <E> E elementAt(Object[] es, int index) {
        return (E) es[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 = https://www.cnblogs.com/angelMask/p/elementData(index);
        elementData[index] = element;
        return oldValue;
    }

    //最尾增加元素,容量不夠就擴1
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        elementCount = s + 1;
    }

    //丟,你沒有回傳false的情況設個boolean?難蚌
    public synchronized boolean add(E e) {
        modCount++;
        add(e, elementData, elementCount);
        return true;
    }

    //就換個名字?
    public boolean remove(Object o) {
        return removeElement(o);
    }

   //就引數調轉一下...
    public void add(int index, E element) {
        insertElementAt(element, index);
    }

    //換了名字又重寫了一遍...和removeElementAt相比加了個回傳值,回傳值是原來的元素
    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() {
        removeAllElements();
    }

    //是否包含集合c的所有元素
    public synchronized boolean containsAll(Collection<?> c) {
        return super.containsAll(c);
    }

    //在vector最后增加c的所有元素
    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;
        if (numNew == 0)
            return false;
        synchronized (this) {
            Object[] elementData = this.elementData;
            final int s = elementCount;
            //確保又足夠的容量
            if (numNew > elementData.length - s)
                elementData = grow(s + numNew);
            //將a從0開始的所有元素拷貝到..., 長度是numNew
            System.arraycopy(a, 0, elementData, s, numNew);
            elementCount = s + numNew;
            return true;
        }
    }

    //先看下面的bulkRemove()
    public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return bulkRemove(e -> c.contains(e));
    }

    //下面
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return bulkRemove(e -> !c.contains(e));
    }

    //下面
    @Override
    public boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        return bulkRemove(filter);
    }

    // A tiny bit set implementation

    private static long[] nBits(int n) {
        return new long[((n - 1) >> 6) + 1];
    }
    private static void setBit(long[] bits, int i) {
        bits[i >> 6] |= 1L << i;
    }
    private static boolean isClear(long[] bits, int i) {
        return (bits[i >> 6] & (1L << i)) == 0;
    }

    //不會
    private synchronized boolean bulkRemove(Predicate<? super E> filter) {
        int expectedModCount = modCount;
        final Object[] es = elementData;
        final int end = elementCount;
        int i;
        // Optimize for initial run of survivors
        for (i = 0; i < end && !filter.test(elementAt(es, i)); i++)
            ;
        // Tolerate predicates that reentrantly access the collection for
        // read (but writers still get CME), so traverse once to find
        // elements to delete, a second pass to physically expunge.
        if (i < end) {
            final int beg = i;
            final long[] deathRow = nBits(end - beg);
            deathRow[0] = 1L;   // set bit 0
            for (i = beg + 1; i < end; i++)
                if (filter.test(elementAt(es, i)))
                    setBit(deathRow, i - beg);
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            modCount++;
            int w = beg;
            for (i = beg; i < end; i++)
                if (isClear(deathRow, i - beg))
                    es[w++] = es[i];
            for (i = elementCount = w; i < end; i++)
                es[i] = null;
            return true;
        } else {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            return false;
        }
    }

    //在特定下標處插入所有集合中的元素
    public synchronized boolean addAll(int index, Collection<? extends E> c) {
        if (index < 0 || index > elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        Object[] a = c.toArray();
        modCount++;
        int numNew = a.length;
        if (numNew == 0)
            return false;
        Object[] elementData = this.elementData;
        final int s = elementCount;
        if (numNew > elementData.length - s)
            elementData = grow(s + numNew);

        int numMoved = s - index;//計算原陣列中index后剩余元素的數量
        if (numMoved > 0)
            System.arraycopy(elementData, index,
                             elementData, index + numNew,
                             numMoved);//轉移index后的元素
        System.arraycopy(a, 0, elementData, index, numNew);//將c賦入elementData
        elementCount = s + numNew;
        return true;
    }

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

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

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

    //切割陣列,其中原始碼中List分為是否實作了RandomAccess(隨機讀取)介面兩種
    //vector是實作了隨機讀取介面的容器,擁有更高的讀寫效率
    //JDK建議實作了隨機讀取的類使用fori遍歷而非iterator
    public synchronized List subList(int fromIndex, int toIndex) {
        return Collections.synchronizedList(super.subList(fromIndex, toIndex),
                                            this);
    }

    //移除范圍中的元素,fromIndex是起始下標,toIndex末尾下標
    protected synchronized void removeRange(int fromIndex, int toIndex) {
        modCount++;
        shiftTailOverGap(elementData, fromIndex, toIndex);
    }

    //lo是fromIndex, hi是toIndex
    private void shiftTailOverGap(Object[] es, int lo, int hi) {
        //將es toIndex后所有的元素拷貝到fromIndex后所有的元素的位置上
        System.arraycopy(es, hi, es, lo, elementCount - hi);
        //將elementCount-(toIndex-fromIndex)后的所有元素置空
        for (int to = elementCount, i = (elementCount -= hi - lo); i < to; i++)
            es[i] = null;
    }

    //序列化介面
    @java.io.Serial
    private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField gfields = in.readFields();
        int count = gfields.get("elementCount", 0);
        Object[] data = https://www.cnblogs.com/angelMask/p/(Object[])gfields.get("elementData", null);
        if (data =https://www.cnblogs.com/angelMask/p/= null && !gfields.defaulted("elementData") && count > 0) {
            // If elementData is null due to 8276665 throwing this exception will not
            // overwrite the original ClassNotFoundException exception.
            // That exception has been recorded and will be thrown from OIS.readObject.
            throw new ClassNotFoundException("elementData is null");
        }
        if (count < 0 || data =https://www.cnblogs.com/angelMask/p/= null || count > data.length) {
            throw new StreamCorruptedException("Inconsistent vector internals");
        }
        elementCount = count;
        elementData = https://www.cnblogs.com/angelMask/p/data.clone();
    }

    //序列化介面
    @java.io.Serial
    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 = https://www.cnblogs.com/angelMask/p/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() {
        return new ListItr(0);//一個繼承Itr并實作了ListIterator的內部類
    }

    public synchronized Iterator<E> iterator() {
        return new Itr();//一個實作了iterator介面的內部類
    }

    private class Itr implements Iterator<E> {
        int cursor;       // 記錄著下一個元素的索引,起點是0,終點是elementCount
        int lastRet = -1; // 記錄著當前元素的索引,lastRet=cursor-1
        int expectedModCount = modCount;//快速失敗機制

        public boolean hasNext() {
            return cursor != elementCount;
        }

        //沒啥好看的
        public E next() {
            synchronized (Vector.this) {
                checkForComodification();
                int i = cursor;
                if (i >= elementCount)
                    throw new NoSuchElementException();
                cursor = i + 1;
                return elementData(lastRet = i);
            }
        }

        //當前的元素被移除,那么lastRet就要指向-1,而cursor就要指向當前元素(因為			  remove()函式是使用arraycopy()實作的)
        public void remove() {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.remove(lastRet);//這里增加了modCount
                expectedModCount = modCount;
            }
            cursor = lastRet;
            lastRet = -1;
        }

        //函式式編程介面Consumer(lambda運算式和方法參考等等)
        @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;
                }
                final Object[] es = elementData;
                if (i >= es.length)
                    throw new ConcurrentModificationException();
                while (i < size && modCount == expectedModCount)
                    action.accept(elementAt(es, i++));//這個將引數傳入你寫的lambda														運算式或者方法參考
                // modCount==expectedModCount實作了快速失敗
                cursor = i;
                lastRet = i - 1;
                checkForComodification();
            }
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

    //和上一個區別不大,也就調了些函式
    final class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super();
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public int nextIndex() {
            return cursor;
        }

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

        public E previous() {
            synchronized (Vector.this) {
                checkForComodification();
                int i = cursor - 1;
                if (i < 0)
                    throw new NoSuchElementException();
                cursor = i;
                return elementData(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;
        }
    }

    /**
     * @throws NullPointerException {@inheritDoc}
     */
    @Override
    public synchronized void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        final Object[] es = elementData;
        final int size = elementCount;
        for (int i = 0; modCount == expectedModCount && i < size; i++)
            action.accept(elementAt(es, i));
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }

    /**
     * @throws NullPointerException {@inheritDoc}
     */
    @Override
    public synchronized void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final int expectedModCount = modCount;
        final Object[] es = elementData;
        final int size = elementCount;
        for (int i = 0; modCount == expectedModCount && i < size; i++)
            es[i] = operator.apply(elementAt(es, i));
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        // TODO(8203662): remove increment of modCount from ...
        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++;
    }

    /**
     * Creates a <em><a href="https://www.cnblogs.com/angelMask/p/Spliterator.html#binding">late-binding</a></em>
     * and <em>fail-fast</em> {@link Spliterator} over the elements in this
     * list.
     *
     * <p>The {@code Spliterator} reports {@link Spliterator#SIZED},
     * {@link Spliterator#SUBSIZED}, and {@link Spliterator#ORDERED}.
     * Overriding implementations should document the reporting of additional
     * characteristic values.
     *
     * @return a {@code Spliterator} over the elements in this list
     * @since 1.8
     */
    @Override
    public Spliterator<E> spliterator() {
        return new VectorSpliterator(null, 0, -1, 0);
    }

    //行百里者半九十,我已經開擺了,
    /** Similar to ArrayList Spliterator */
    final class VectorSpliterator implements Spliterator<E> {
        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

        /** Creates new spliterator covering the given range. */
        VectorSpliterator(Object[] array, int origin, int fence,
                          int expectedModCount) {
            this.array = array;
            this.index = origin;
            this.fence = fence;
            this.expectedModCount = expectedModCount;
        }

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

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

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

        @SuppressWarnings("unchecked")
        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            final int hi = getFence();
            final Object[] a = array;
            int i;
            for (i = index, index = hi; i < hi; i++)
                action.accept((E) a[i]);
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

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

        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }

    void checkInvariants() {
        // assert elementCount >= 0;
        // assert elementCount == elementData.length || elementData[elementCount] == null;
    }
}

ArrayList刨析

因為和Vector一樣都是實作了抽象類AbstractList所以本質上是一樣的,不同的是,Vector的實作因為考慮了多執行緒的因素,原始碼應該會比ArrayList更高級,相應的,因為Vector考慮了多執行緒所以也會降低方法執行的速度和效率,

Stack刨析

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

    //在Vector陣列尾部壓入資料
    public E push(E item) {
        addElement(item);

        return item;
    }

    //回傳并移除資料尾部元素
    public synchronized E pop() {
        E       obj;
        int     len = size();

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

        return obj;
    }

    //回傳陣列尾部元素
    public synchronized E peek() {
        int     len = size();

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

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

    //從尾部開始找到最找出現o的下標
    public synchronized int search(Object o) {
        int i = lastIndexOf(o);

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

   //序列化
    @java.io.Serial
    private static final long serialVersionUID = 1224463164541339165L;
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/499307.html

標籤:Java

上一篇:竟然有一半的人不知道 for 與 foreach 的區別???

下一篇:深入理解Java中的ThreadLocal

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more