序文
この記事では、我々は、Listインタフェースを実装し、別のコンテナクラス、ArrayListのを、分析、実装クラスがリストされ、基礎となる実装が配列で、私たちは以下に詳細に分析してみましょう。PS:いくつかの時間前など、あらゆる種類のものに加えて最終試験を設定し、学校の実験室のコースは、長い時間のためにブログを更新しなかったので...
1.概要
ランダム・ArrayListクラスがインタフェースを実装して、ランダムアクセスをサポートしています。
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
复制代码
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;复制代码
2.拡張
ことに留意すべきである操作の膨張はまた、スレッド安全でない動作です。国境を越えたアクセスの問題は、アレイは、マルチスレッド環境で表示されますので、この行のステートメントは、アトミック操作ではありません。だから、HashMapのと同様のArrayListは、スレッドセーフコンテナです。
elementData[size++] = e;复制代码
以下は、新しい要素は、ソースコードと拡張操作中に挿入されます。
//插入新元素
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
//这里会产生数组越界问题,因为下面这行语句并不是一个原子操作
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//扩容
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//新容量为旧容量的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}复制代码
3.要素を削除します
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}复制代码
4.フェイルファスト
約4.1は、フェイルファスト
フェイルファストつのエラー機構のメカニズムのJavaコレクション(コレクション)。複数のスレッドがコンテンツの同じセット上で動作している場合、それはフェイルファストイベントを発生させることができます。
たとえば、次のセットは、他のスレッドによって変更された場合、スレッドは収集プロセスを横断するイテレータ、コンテンツ場合、次に、スレッドAは、コレクションにアクセスし、例外がConcurrentModificationExceptionをスローするフェイルファストイベントを生成します。
フェイルファスト4.2 ArrayListの中
ArrayListのmodCountは、構造の変化の回数を記録するために使用しました。操作、又は内部配列の構造内のすべての変更のサイズを調整するには追加または削除される少なくとも1つの要素を、要素の値だけではない構造の変化を設定することを意味します。
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}复制代码
のシーケンス
transient Object[] elementData; // non-private to simplify nested class access复制代码
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in capacity
s.readInt(); // ignored
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}复制代码
ArrayList list = new ArrayList();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(list);复制代码
6.まとめ
ビューのソースポイントからのArrayList)は、いくつかの論文は、追加するいくつかの一般的に使用される方法、(と内部データ構造のArrayListを解析HashMapのより幾分単純である必要はない)(削除。それはまた、ArrayListの中でフェイルファストを紹介し、マルチスレッド環境でスレッドセーフなコンテナである理由あなたがマルチスレッド環境で使用したい場合は、ベクトルCopyOnWriteArrayListとか、二つの容器を使用することを検討して議論しましたアプリケーションとのArrayListのシリアル化の問題。
最後に、私はまた、この記事の欠点を指摘し、お互いに議論するあなたを歓迎します。