転載、複製ようこそ、あなたに感謝し、ソースを明記してください。
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を変更することでクリアすべきです。