Java下位層のArrayList下位層実現原理
ArrayListの概要
ArrayListは動的配列であり、Arrayの複雑なバージョンに相当し、動的な増加と減少要素を提供し、CollectionとListインタフェースを実現し、配列の大きさを柔軟に設定することができる.なお、ArrayListはスレッドセキュリティではないので、一般的には単一スレッドでArrayListを使用することを推奨します.ArrayListの要素はnullであってもよい.
ソース解析
ArrayListの下部には配列格納要素が使用され、デフォルトの配列サイズは10です.
1. indexOf(Object o)メソッド
2.LastIndexOf(Object o)メソッド
3.get(int index)メソッド
4. add(E e)法:配列容量が足りない場合、拡張は元の1.5倍になる
4. set(int index,E element)メソッド:元の位置の要素を置換する
5.add(int index,E element)メソッド:要素を挿入し、後ろの要素を後ろに移動
6.remove(int index)メソッド
ArrayListは動的配列であり、Arrayの複雑なバージョンに相当し、動的な増加と減少要素を提供し、CollectionとListインタフェースを実現し、配列の大きさを柔軟に設定することができる.なお、ArrayListはスレッドセキュリティではないので、一般的には単一スレッドでArrayListを使用することを推奨します.ArrayListの要素はnullであってもよい.
ソース解析
ArrayListの下部には配列格納要素が使用され、デフォルトの配列サイズは10です.
//
private static final int DEFAULT_CAPACITY = 10;
//
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
1. indexOf(Object o)メソッド
// ,
public int indexOf(Object o) {
// null, null
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
// ,
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
// -1
return -1;
}
2.LastIndexOf(Object o)メソッド
// , , indexOf
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
// ,indexOf
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
3.get(int index)メソッド
//
public E get(int index) {
//
rangeCheck(index);
//
return elementData(index);
}
private void rangeCheck(int index) {
// ,
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
4. add(E e)法:配列容量が足りない場合、拡張は元の1.5倍になる
//
public boolean add(E e) {
// ,
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
// ArrayList , ,minCapacity minCapacity
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// , ( ,minCapacity , +1)
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
//
int oldCapacity = elementData.length;
// + /2
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//
elementData = Arrays.copyOf(elementData, newCapacity);
}
4. set(int index,E element)メソッド:元の位置の要素を置換する
public E set(int index, E element) {
// index
rangeCheck(index);
E oldValue = elementData(index);
//
elementData[index] = element;
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
5.add(int index,E element)メソッド:要素を挿入し、後ろの要素を後ろに移動
public void add(int index, E element) {
// ,
rangeCheckForAdd(index);
//
ensureCapacityInternal(size + 1);
// ,
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//
elementData[index] = element;
size++;
}
6.remove(int index)メソッド
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);
// null
elementData[--size] = null;
return oldValue;
}