ArrayListのソース解析(B)

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/dengyu810/article/details/102731084

転載、複製ようこそ、あなたに感謝し、ソースを明記してください。

https://www.cnblogs.com/sx-wuyj/p/11177257.html

自身のレコードArrayListのソースを学びました。

以前は、継続ArrayListのソースコードを解析する(A)

  • addll(コレクションC <拡張E?>):オリジナルの収集対象のコレクションに加えます。

     //参数需要是Collection的子类
        public boolean addAll(Collection<? extends E> c) {
            //将C集合通过toArray()方法转为数组
            Object[] a = c.toArray();
            //拿到传入数组的长度
            int numNew = a.length;
            //对底层数组进行扩容
            ensureCapacityInternal(size + numNew);  // Increments modCount
            //复制数组
            System.arraycopy(a, 0, elementData, size, numNew);
            //将size更新为size+numNew
            size += numNew;
            //返回boolean
            return numNew != 0;
        }

    ensureCapacityInternal(サイズ+ numNew)。

    この方法では、詳細な説明は、あなたが行くことができた上のブログについてと見ます
  • 追加(int型のインデックス、コレクションcは<Eを拡張?>):オリジナルの収集対象セット指定された場所に追加

    public boolean addAll(int index, Collection<? extends E> c) {
            //检验index
            rangeCheckForAdd(index);
            //将C集合通过toArray()方法转为数组
            Object[] a = c.toArray();
            //拿到传入数组的长度
            int numNew = a.length;
            //对底层数组进行扩容
            ensureCapacityInternal(size + numNew);  
            //计算需要复制的长度
            int numMoved = size - index;
            //需要复制的长度如果大于0,通过arraycopy方法复制
            if (numMoved > 0)
                System.arraycopy(elementData, index, elementData, index + numNew,
                                 numMoved);
            //将参数数组复制到底层数组index位置.
            System.arraycopy(a, 0, elementData, index, numNew);
            //修改size的值  为size+numNew
            size += numNew;
            //返回boolean
            return numNew != 0;
        }

    実際には、膨張機構の理解限りのaddAll()メソッドは、他のコンテンツが非常に簡単であるが、この方法は、インデックスに従って時間を挿入することに留意すべきです。

    if (numMoved > 0)
        System.arraycopy(elementData, index, elementData, index + numNew,numMoved);
    
    System.arraycopy(a, 0, elementData, index, numNew);

    あなたが戻って挿入位置の後の要素が必要な場合は、実際には根本的な配列の中央に挿入位置かどうかを判断し:?意味の別の層があるとき、あなたは二回最初の裁判官を、それをコピーしたいなぜあなたは不思議に思うかもしれません、ソースコードを参照してください。新しい配列にコピーされ、モバイル、

    第二のコピーは、2つの数の組合せは、基礎となる配列である配列です。

  • (int型のインデックス)を取得:指定された位置にある要素を取得します。

     public E get(int index) {
            rangeCheck(index);
            return elementData(index);
        }

    メソッドの誰もがソースコードに精通して取得し、おそらくrangeCheck()メソッドは、比較的なじみのない、また非常に簡単です。

     private void rangeCheck(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

    より多くの何も、我々はインデックスが最大サイズを超えることはできません渡し、これはよく理解されていません。

  • セット(INTインデックス、E素子):位置で要素を変更

    public E set(int index, E element) {
            rangeCheck(index);
    
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }

    ジェネリック医薬品の使用は、私たちは私たちの仕事を考えると、コレクション内の型の要素を学ぶことができる理由の着信パラメータが十分理解されるように実際には、この方法は、要素indxe根底にある配列要素を変更することで設定の原則は、さまざまな合格しましたそれは、ジェネリックを使用して、この場所での利点であることは言うまでもないです。

    もう一つのポイントは、戻り値が変更された要素であり、私が前に気づかなかった、方法が義務に戻るように設定されていることです。

  • サイズ():セットサイズ

    public int size() {
            return size;
        }
  • 最初の発生のセット内の要素の位置:のindexOf(オブジェクトo)

     //集合中某个元素第一次出现的位置
        public int indexOf(Object o) {
            //判断传入o是否为null
            if (o == null) {
                //如果为null,循环遍历寻找为null的索引位置
                for (int i = 0; i < size; i++)
                    //因为传入的是一个对象,为null使用==
                    if (elementData[i]==null)
                        //返回出现的位置
                        return i;
            } else {
                //如果不为null,使用equals寻找传输对象位置
                for (int i = 0; i < size; i++)
                    if (o.equals(elementData[i]))
                        //找到返回对象位置
                        return i;
            }
            //找不到对象情况下返回-1
            return -1;
        }

    このメソッドは、渡されたヌル==時間を探しに行くために必要とされている場合、ことに留意すべきです。

  • 位置要素は、最後に出現を返す:のlastIndexOf(オブジェクトO)

    public int lastIndexOf(Object o) {
          //判断传入o是否为null
            if (o == null) {
                //如果为null,循环遍历寻找为null的索引位置
                //这里是倒序遍历
                for (int i = size-1; i >= 0; i--)
                    if (elementData[i]==null)
                        return i;
            } else {
                //如果不为null,使用equals寻找传输对象位置
                //同样是倒序遍历
                for (int i = size-1; i >= 0; i--)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }

    実際には、indeOf()とのlastIndexOfを()思考の2つの方法が同じで、違いは正順トラバーサル、逆方向移動です。

  • クローン():クローニング

    public Object clone() {
            try {
                //调用了父类也就是Object的clone.
                ArrayList<?> v = (ArrayList<?>) super.clone();
                //集合V的底层数组复制一个原集合底层数组
                v.elementData = Arrays.copyOf(elementData, size);
                v.modCount = 0;
                //返回V集合
                return v;
            } catch (CloneNotSupportedException e) {
               // this shouldn't happen, since we are Cloneable
                throw new InternalError(e);
            }
        }

    私は個人的にはこのメソッドは、戻り値はArrayListをすることができないで戻って、ソースから見たとvはArrayListの。ArrayListにもトップレベルの親クラスのオブジェクトであることができる。だから、これはあまりにも間違っていないと思われます。

    try-catch我々がクローン化されているので、コメントでは、それが起こらないことを意味

  • toArray():配列型オブジェクトのインストールのセット

    public Object[] toArray() {
            return Arrays.copyOf(elementData, size);
        }

    実際には、この方法は、ここで展開されません)は、低レベルの呼び出しがまだSystem.arraycopyの(と呼ばれ、基本的な配列のコピーに戻りますと述べました。

  • toArray(T [] A):指定されたタイプのアレイにインストールセット

     public <T> T[] toArray(T[] a) {
            //如果参数数组的长度小于size,那么直接转换为参数数组类型
            if (a.length < size)
                // Make a new array of a's runtime type, but my contents:
                return (T[]) Arrays.copyOf(elementData, size, a.getClass());
            System.arraycopy(elementData, 0, a, 0, size);
            //如果参数数组长度大于size
            //那么返回去的数组[size]为null
            if (a.length > size)
                a[size] = null;
            return a;
        }

    2つのオーバーロードされた方法との間のこの差が第1のタイプのオブジェクトの配列を返すことで、第二は、指定された型の配列を返します。

  • (int型のインデックス)を削除します。場所に要素を削除

     public E remove(int index) {
            //校验
            rangeCheck(index);
            modCount++;
            //被删除的元素
            E oldValue = elementData(index);
            //需要被复制的元素个数
            int numMoved = size - index - 1;
            //如果被复制的元素个数大于0,那么就复制一个数组
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            //将底层数组最后一个元素设置为null
            //让GC开始工作
            elementData[--size] = null;
            //返回被删除的元素
            return oldValue;
        }

    コピーされた要素0以下のGeプライム場合、それは要素の端部は、素子の位置を変更する必要が削除されないことを意味します。

  • (オブジェクトo)削除:指定された要素を削除します

     public boolean remove(Object o) {
            //判断需要删除的对象是否为null
            if (o == null) {
                //遍历底层数组,使用==null来寻找
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) {
                        fastRemove(index);
                        return true;
                    }
            } else {
                //如果不是null,是一个对象
                //遍历底层数组,使用equals来寻找
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
            }
            //如果没有找到返回false
            return false;
        }

    また、過負荷請求fastRemove()メソッドと(削除)論理的に一貫性のあるが、戻り値とプライベート修飾子が存在しない、それはプライベートな方法です。

      private void fastRemove(int index) {
            modCount++;
            // //需要被复制的元素个数
            int numMoved = size - index - 1;
            //如果被复制的元素个数大于0,那么就复制一个数组
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            //将底层数组最后一个元素设置为null
            //让GC开始工作
            elementData[--size] = null; // clear to let GC do its work
        }
  • クリーン():空のセットになるために、明確な内部要素を設定

     public void clear() {
            modCount++;
    
            // clear to let GC do its work
            for (int i = 0; i < size; i++)
                elementData[i] = null;
    
            size = 0;
        }

    これは、アレイの底部を通ってループし、基礎となる配列がヌルに設定されているの要素の全て、及びサイズ0を変更することでクリアすべきです。

理解するためのいくつかの個人的なシンプル。法のない書かれた部分はありません。リミテッド時間と空間は、私が続けてアップデートする前に、まず最初に書き込みます。

よる読みの過程で。私は、見当違いの希望をもたらすために限定されている場合、その兄でき批判。共通の進捗状況

おすすめ

転載: blog.csdn.net/dengyu810/article/details/102731084