ArrayList底層源碼詳解(擴展)
ArrayList(擴展)
除了常用的增刪改查,ArrayList還提了其他的操作集合的方法,他們的源碼實現通過這篇文章來進行解析。
- addAll(Collection<? extends E> c)將集合中的所有元素添加到當前集合的末尾。
/**
* 1. 將目標集合轉換爲數組
* 2. 確保集合長度
* 3. 將目標數組內容拷貝到當前數組的最後
* 4. 更新集合的容量
* 5. 根據目標數組的容量返回boolean判斷是否成功。
*/
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
- addAll(int index, Collection<? extends E> c)將目標集合的元素從指定索引位置開始添加到當前集合中,並且將原本位置的元素向後移動目標集合長度的位置
/**
* 1. 將目標集合轉換爲數組
* 2. 確保集合長度
* 3. 計算元素需要移動的長度,然後將原本位置的元素向後移動指定長度。
* 4. 將目標數組複製到index位置
* 5. 根據目標數組的容量返回boolean判斷是否成功。
*
*/
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
- removeAll(Collection<?> c)刪除當前集合和目標集合中元素相等的值。
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
//如果當前集合中不存在目標集合中的值,就將改元素存放到當前數組的w索引處
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
// 當c.contains() 拋出空指針異常的時候將r後的元素附加到w位置後面
// 在某種情況下 c.contain()可能會拋出空指針的異常,出於安全考慮,進行如下操作
//對於空指針下面的例子就會出現
// public static boolean doesContain(Integer i) {
// return array.contains(Integer.toString(i));
// }
//
// public static void main(String[] args) {
// System.out.println(doesContain(null));
// }
if (r != size) {
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
//將剩餘元素清空
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
4 retainAll(Collection<?> c) 取目標集合和當前集合的交集
// 此操作和remove相反 取相同的值 通過complement=true來控制
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
5 replaceAll(UnaryOperator operator)將集合中所有的值替換爲指定值
/**
* UnaryOperator 通過傳入函數方法來進行替換值
*/
@Override
@SuppressWarnings("unchecked")
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
elementData[i] = operator.apply((E) elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
例子如下所示:
List<Integer> list = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
list.add(i);
}
list.replaceAll(a -> a + 10);
System.out.println(list);