ArrayList源码分析
ArrayList 是一个可动态扩展的数组,其底层实现是数组。
- 它是如何实现动态扩容的?
- 调用无参构造创建的ArrayList 对象,初始化的容量真的为10吗?
- elementData 被transient 修饰,那它是如何实现序列化与反序列化的?
- ArrayList 增删改查的方法时间复杂度又各是多少?
- ArrayList 的数组越界的定义规则是什么?
- ConcurrentModificationException 定义规则是什么?
- 为什么在ArrayList 遍历中对其进行增删,会抛出ConcurrentModificationException异常,用迭代器对ArrayList 进行遍历的时候,调用迭代器的增删方法对ArrayList 进行增删的时候为什么不会抛出ConcurrentModificationException 异常?
属性
public class ArrayList<E> extends AbstractList<E> implements List<E>,
RandomAccess, Cloneable, java.io.Serializable {
...
private static final long serialVersionUID = 8683452581122892189L;
// 化默认初始容量
private static final int DEFAULT_CAPACITY = 10;
/**
* 指定该ArrayList容量为0时,返回该空数组。
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 当调用无参构造方法,返回的是该数组。刚创建一个ArrayList 时,其内数据量为0。
* 它与EMPTY_ELEMENTDATA的区别就是:该数组是默认返回的,而后者是在用户指定容量为0时返回。
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存储ArrayList元素的数组缓冲区,ArrayList的容量是这个数组缓冲区的长度。
* 任何使用elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA清空ArrayList将在添加第一个元素时扩展为DEFAULT_CAPACITY。
**/
transient Object[] elementData;
// ArrayList的实际元素大小(数组中包含的元素个数)
private int size;
/**
* 要分配的数组的最大大小。
* 一些VM在数组中保留一些头信息。
* 尝试分配更大的数组可能会导致OutOfMemoryError:请求的数组大小超过VM限制
**/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 这个属性是在AbstractList 类中的,记录对List 被修改的次数,主要使用是在`Iterator`,
* 是防止在迭代的过程中集合被修改。在ArrayList的所有涉及结构变化的方法中都增加
* modCount的值,包括:add()、remove()、addAll()、removeRange()及
* clear()方法。这些方法每调用一次,modCount的值就加1。
* 注:add()及addAll()方法的modCount的值是在其中调用的ensureCapacity()方法中增加的。
*/
protected transient int modCount = 0;
......
}
构造方法
/**
* Constructs an empty list with the specified initial capacity.
* 构造具有指定初始容量的 List。
* @param initialCapacity List 的初始化容量
* @throws IllegalArgumentException 如果初始化容量为负数时,抛出该异常
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 构造一个长度为10 的List,此时并不会直接构建一个长度为10的List 对象
* 调用该构造生成的List 对象是长度为0的:DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}
* 当调用add(E e)、add(int index, E element)、addAll(Collection<? extends E> c)、addAll(int index, Collection<? extends E> c) 才会调用ensureCapacityInternal(int minCapacity) 创建一个长度为10的List 对象
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 按照集合迭代器返回元素的顺序构造包含指定集合的元素的List对象。
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public ArrayList(Collection<? extends E> c) {
// 将集合c 转成数组
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
方法
序号 | 返回类型 | 方法 | 时间复杂度 |
---|---|---|---|
1 | boolean | add(E e) 将指定的元素追加到此lis的末尾 | |
2 | void | add(int index, E element) 将指定元素插入到列表中的指定位置。 | |
3 | boolean | addAll(Collection<? extends E> c) 将指定的元素追加到此lis的末尾 | |
4 | boolean | addAll(int index, Collection<? extends E> c) 将指定的元素追加到此lis的指定索引处 | |
5 | void | clear() 从列表中删除所有元素。 | |
6 | Object | clone() 返回此ArrayList实例的浅克隆。 | |
7 | boolean | contains(Object o) 如果此List 包含指定的元素,则返回true。 | |
8 | void | ensureCapacity(int minCapacity) 增加arraylist实例的容量,以确保它至少可以容纳由minCapacity参数指定的元素数(如果需要的话) | |
9 | void | forEach(Consumer<? super E> action) 为可迭代的每个元素执行给定的操作,直到处理完所有元素或操作引发异常为止。 | |
10 | E | get(int index) 返回列表中指定位置的元素。 | |
11 | int | indexOf(Object o) 返回此列表中指定元素的第一个出现项的索引,如果该列表不包含该元素,则返回-1 | |
12 | boolean | isEmpty() 如果此列表不包含任何元素,则返回true。 | |
13 | Iterator | iterator() 按特有的顺序返回列表中元素的Iterator 对象。 | |
14 | int | lastIndexOf(Object o) 回此列表中指定元素的最后一次出现的索引,如果该列表不包含该元素,则返回-1。 | |
15 | ListIterator | listIterator() 返回列表中元素的ListIteratorr对象(按特有的顺序)。 | |
16 | ListIterator | listIterator(int index) 从列表中的指定位置开始,返回列表中元素的ListIterator对象(按特有的顺序),。 | |
17 | E | remove(int index) 移除列表中指定位置的元素。 | |
18 | boolean | remove(Object o) 从列表中删除指定元素的第一个出现项(如果存在)。 | |
19 | boolean | removeAll(Collection<?> c) 从该列表中删除指定集合中包含的所有元素。 | |
20 | boolean | removeIf(Predicate<? super E> filter) 移除此集合中满足给定predicate的所有元素 | |
21 | void | removeRange(int fromIndex, int toIndex) 返回列表中指定位置的元素。 | |
22 | void | replaceAll(UnaryOperator operator) Replaces each element of this list with the result of applying the operator to that element. | |
23 | boolean | retainAll(Collection<?> c) 只保留此列表中包含在指定集合中的元素。 | |
24 | E | set(int index, E element) 用指定的元素替换列表中指定位置的元素。 | |
25 | int | size() 返回此列表中的元素数量。 | |
26 | void | sort(Comparator<? super E> c) 根据指定c对该列表进行排序。 | |
27 | Spliterator | spliterator() 在其中的元素上创建一个late-binding 和 fail-fast Spliterator | |
28 | List | subList(int fromIndex, int toIndex) 返回列表中指定的fromIndex(包含)和toIndex(不包含)之间的部分。 | |
29 | Object[] | toArray() 返回一个数组,该数组按特有的顺序(从第一个元素到最后一个元素),包含列表中的所有元素。 | |
30 | <T> T[] | toArray(T[] a) 返回一个数组,该数组按特有的顺序(从第一个元素到最后一个元素),包含列表中的所有元素; 返回数组的运行时类型是指定数组的运行时类型。 | |
31 | void | trimToSize() 将ArrayList实例的容量调整为列表的当前大小。 |
java里的clone分为:
- 浅复制(浅克隆):浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。
- 深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍。
1. 添加方法
/**
* 将指定元素添加到列表末尾
*
* 平均时间复杂度为 O(1),最坏的时间复杂度O(n)
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
/**
* 将指定元素插入其中的指定位置列表。
* 将当前位于该位置(如果有)的元素移动,并将右边的元素顺序往后移动一位
*
* 最好的时间复杂度为:O(1),最坏的时间复杂度为 O(n),平均时间复杂度为:O(n)
*
* @param index index at which the specified element is to be inserted
* @param element element to be inserted
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
/**
* 将指定的元素追加到此lis的尾部
*
* 时间复杂度为O(n)
*
* @param c collection containing elements to be added to this list
* @return <tt>true</tt> if this list changed as a result of the call
* @throws NullPointerException if the specified collection is null
*/
public boolean addAll(Collection<? extends E> c) {
// 将要添加的集合转成数组
Object[] a = c.toArray();
// 获取数组的长度
int numNew = a.length;
// 重新确认ArrayList 的容量
ensureCapacityInternal(size + numNew); // Increments modCount
// 将要添加数据按原顺序一次追加到elementData 的尾部
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
/**
* 将指定的元素追加到此lis指定索引处,并将此list 原来指定索引及之后的所有元素
* 依次后移一位
*
* 时间复杂度为O(n)
*
* @param index index at which to insert the first element from the
* specified collection
* @param c collection containing elements to be added to this list
* @return <tt>true</tt> if this list changed as a result of the call
* @throws IndexOutOfBoundsException {@inheritDoc}
* @throws NullPointerException if the specified collection is null
*/
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;
}
// -----------------------------------------------------------------------------
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 要分配的数组的最大大小。
* Some VMs reserve some header words in an array.
* 尝试分配更大的数组可能会导致 OutOfMemoryError: R请求的数组大小超过VM限制
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 增加能力,以确保它至少可以持有由最小容量参数指定的元素数量。
*
* @param minCapacity 所需的最小容量
*/
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
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);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
java.lang.System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length):
- src:原数组
- srcPos:原数组的开始位置
- dest:目标数组
- destPos:目标数组的开始位置
- length:要拷贝的元素个数
2. 删除方法
/**
*
* 从列表中删除指定索引处的元素,并返回被删除的元素,如果它存在的话。
*/
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;
}
/**
*
* 从列表中删除指定元素的第一个出现项,如果它存在的话。
* 如果列表不包含该元素,则它包含不变。更正式地说,删除索引最小的元素
*/
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
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
}
/**
* 从该列表中删除索引位于fromIndex 到toIndex 两者之间的所有元素
* 包含 fromIndex; 排除:toIndex。
*/
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);
// clear to let GC do its work
int newSize = size - (toIndex-fromIndex);
for (int i = newSize; i < size; i++) {
elementData[i] = null;
}
size = newSize;
}
/**
* 从该列表中删除指定集合中包含的所有元素。
*/
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
/**
* 只保留集合中包含的所有元素,集合以外的元素都删除。
*/
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
/**
* 从该列表中删除指定集合中包含的所有元素。
*/
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++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
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;
}
3. removeIf 方法
/**
*
*/
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
// 找出要删除的元素
// any exception thrown from the filter predicate at this stage
// will leave the collection unmodified
int removeCount = 0;
final BitSet removeSet = new BitSet(size);
final int expectedModCount = modCount;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
@SuppressWarnings("unchecked")
final E element = (E) elementData[i];
if (filter.test(element)) {
// 将符合条件的索引存到 BigSet 集合中
removeSet.set(i);
removeCount++;
}
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
// 将剩余元素移动到已删除元素所留下的空间上
final boolean anyToRemove = removeCount > 0;
if (anyToRemove) {
final int newSize = size - removeCount;
for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
// 如果removeSet 中含有 i,获得是 i + 1;没有时获得是 i 本身
i = removeSet.nextClearBit(i);
elementData[j] = elementData[i];
}
for (int k=newSize; k < size; k++) {
elementData[k] = null; // Let gc do its work
}
this.size = newSize;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
return anyToRemove;
}
3.1 removeIf 方法的使用
public void removeIfDemo() {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
list.add("8");
list.add("9");
list.add("10");
System.out.println(list);
list.removeIf(l -> {
// Predicate 匿名实现类,重写test 方法
if (l.equals("1")) {
return true;
} else {
return false;
}
});
/**
* list.removeIf(new Predicate<String>() {
* @Override
* public boolean test(String s) {
* if (s.equals("1")) {
* return true;
* } else {
* return false;
* }
* }
* });
*/
System.out.println(list);
}
// 运行结果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[2, 3, 4, 5, 6, 7, 8, 9, 10]
4. 替换方法
/**
* 替换list 集合中的元素
*/
@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++;
}
4.1 replaceAll 方法的使用
public void replaceAllDemo() {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
list.add("7");
list.add("8");
list.add("9");
list.add("10");
System.out.println(list);
list.replaceAll(l -> {
if (!l.equals("2")) {
return "11";
} else {
return l;
}
});
// list.replaceAll(new UnaryOperator<String>() {
// @Override
// public String apply(String s) {
// if (!s.equals("2")) {
// return "11";
// } else {
// return s;
// }
// }
// });
System.out.println(list);
// 运行结果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[11, 2, 11, 11, 11, 11, 11, 11, 11, 11]
}
5. sort 方法
@Override
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
5.1 sort 方法的使用
public void sortDemo {
ArrayList<Demo> list = new ArrayList<>();
Demo demo = new Demo();
demo.setAge(10);
demo.setName("三三");
list.add(demo);
demo = new Demo();
demo.setAge(20);
demo.setName("尔尔");
list.add(demo);
demo = new Demo();
demo.setAge(50);
demo.setName("五五");
list.add(demo);
demo = new Demo();
demo.setAge(2);
demo.setName("琪琪");
list.add(demo);
System.out.println(list);
list.sort((demo1, demo2) -> {
if (demo1 == null || demo2 == null) {
return 0;
}
if (demo1.getAge() > demo2.getAge()) {
return 1;
} else if (demo1.getAge() == demo2.getAge()) {
return 0;
} else {
return -1;
}
});
// list.sort(new Comparator<Demo>() {
// @Override
// public int compare(Demo demo1, Demo demo2) {
// if (demo1 == null || demo2 == null) {
// return 0;
// }
// if (demo1.getAge() > demo2.getAge()) {
// return 1;
// } else if (demo1.getAge() == demo2.getAge()) {
// return 0;
// } else {
// return -1;
// }
// }
// });
System.out.println(list);
}
private static class Demo {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Demo{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// 测试结果
[Demo{name='三三', age=10}, Demo{name='尔尔', age=20}, Demo{name='五五', age=50}, Demo{name='琪琪', age=2}]
[Demo{name='琪琪', age=2}, Demo{name='三三', age=10}, Demo{name='尔尔', age=20}, Demo{name='五五', age=50}]
6. forEach 方法
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
// 在使用forEach方法在进行元素的操作的时候,
// 发现ArrayList的数据发生了动,就由forEach方法抛出异常
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
7. ArrayList 迭代器
7. 1 ListIterator
/**
* 返回列表中元素的列表迭代器,从列表中的指定位置开始遍历
* An initial call to {@link ListIterator#previous previous} would
* return the element with the specified index minus one.
*
* <p>The returned list iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public ListIterator<E> listIterator(int index) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index);
return new ListItr(index);
}
/**
* 按特有的顺序返回列表中元素的ListIterator。
*
* <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
*
* @return an iterator over the elements in this list in proper sequence
*/
public ListIterator<E> listIterator() {
return new ListItr(0);
}
/**
* An optimized version of AbstractList.ListItr
*/
private class ListItr extends Itr implements ListIterator<E> {
ListItr(int index) {
super();
cursor = index;
}
public boolean hasPrevious() {
return cursor != 0;
}
public int nextIndex() {
return cursor;
}
public int previousIndex() {
return cursor - 1;
}
@SuppressWarnings("unchecked")
public E previous() {
checkForComodification();
int i = cursor - 1;
if (i < 0)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i;
return (E) elementData[lastRet = i];
}
public void set(E e) {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.set(lastRet, e);
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
public void add(E e) {
checkForComodification();
try {
int i = cursor;
ArrayList.this.add(i, e);
cursor = i + 1;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
7. 2 Iterator
/**
* 按特有的顺序返回列表中元素的迭代器。
*
* <p>The returned iterator is <a href="#fail-fast"><i>fail-fast</i></a>.
*
* @return an iterator over the elements in this list in proper sequence
*/
public Iterator<E> iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
7. 3 Spliterator
/**
* Creates a late-binding and fail-fast Spliterator over the elements in this list.
* 在此列表中的元素上创建延迟绑定(late-binding)和快速失败(fail-fast)的 Spliterator。
*
* @since 1.8
*/
@Override
public Spliterator<E> spliterator() {
return new ArrayListSpliterator<>(this, 0, -1, 0);
}
/**
* 基于索引的二分法,延迟初始化的Spliterator
* */
static final class ArrayListSpliterator<E> implements Spliterator<E> {
private final ArrayList<E> list;
// 当前位置(包含),advance/split操作时会修改
private int index; // current index, modified on advance/split
// 结束位置(不包含),-1 表示到最后一个元素
private int fence;
// 用于存放list的modCount,
private int expectedModCount; // initialized when fence set
/** Create new spliterator covering the given range */
ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
int expectedModCount) {
this.list = list; // OK if null unless traversed
this.index = origin;
this.fence = fence;
this.expectedModCount = expectedModCount;
}
//获取结束位置(存在意义:首次初始化石需对fence 和expectedModCount 进行赋值)
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
ArrayList<E> lst;
if ((hi = fence) < 0) {
if ((lst = list) == null)
// list 为 null时,fence=0
hi = fence = 0;
else {
// 初始化expectedModCount 和 fence
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}
// 分割list,返回一个新分割出的spliterator实例
public ArrayListSpliterator<E> trySplit() {
//hi 为当前的结束位置 lo 为起始位置
int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
return (lo >= mid) ? null : // divide range in half unless too small
new ArrayListSpliterator<E>(list, lo, index = mid,
expectedModCount);
}
/**
*
* 返回true 时,只表示可能还有元素未处理;返回false 时,没有剩余元素处理了
* 该方法只处理首个所有未处理元素
*/
public boolean tryAdvance(Consumer<? super E> action) {
if (action == null)
throw new NullPointerException();
int hi = getFence(), i = index;
if (i < hi) {
index = i + 1;
@SuppressWarnings("unchecked") E e = (E)list.elementData[i];
// 可以在accept 方法中定义处理的逻辑
action.accept(e);
// 检查 accept 方法中是否修改了list 的结构
if (list.modCount != expectedModCount)
throw new ConcurrentModificationException();
return true;
}
return false;
}
// 顺序遍历处理所有剩下的元素
public void forEachRemaining(Consumer<? super E> action) {
int i, hi, mc; // hoist accesses and checks from loop
ArrayList<E> lst; Object[] a;
if (action == null)
throw new NullPointerException();
if ((lst = list) != null && (a = lst.elementData) != null) {
if ((hi = fence) < 0) {
mc = lst.modCount;
hi = lst.size;
}
else
mc = expectedModCount;
if ((i = index) >= 0 && (index = hi) <= a.length) {
for (; i < hi; ++i) {
@SuppressWarnings("unchecked") E e = (E) a[i];
action.accept(e);
}
// 遍历结束判断是否变更过list 的结构
if (lst.modCount == mc)
return;
}
}
throw new ConcurrentModificationException();
}
// 估算还剩下多少个元素需要遍历
public long estimateSize() {
return (long) (getFence() - index);
}
public int characteristics() {
return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
}
}
7. 3 spliterator 方法的使用
public static void demo1() {
ArrayList<String> list = new ArrayList<> ();
list.add ("1");
list.add ("2");
list.add ("3");
list.add ("4");
list.add ("5");
list.add ("6");
list.add ("7");
list.add ("8");
// iterator 长度为8
Spliterator<String> iterator = list.spliterator ();
// iterator 长度为4,spliterator 长度为4
Spliterator<String> spliterator = iterator.trySplit ();
// iterator 长度为4,spliterator 长度为2,stringSpliterator 长度为2
Spliterator<String> stringSpliterator = spliterator.trySplit ();
// 只处理首个所有未处理的元素
iterator.tryAdvance (l -> {
out.print (l + " "); // 5
});
System.out.println ();
// 顺序遍历处理所有剩下的元素
iterator.forEachRemaining (l -> {
out.print (l + " "); // 6 7 8
});
System.out.println ();
spliterator.forEachRemaining (l -> {
out.print (l + " ");// 3 4
});
System.out.println ();
stringSpliterator.forEachRemaining (l -> {
out.print (l + " ");// 1 2
});
System.out.println ();
}
8. ArrayList 的Stream
public static void demo2() {
List<Integer> numbers = new ArrayList<> (Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9));
for (int i = 0; i < 10; i++) {
numbers.add (i + 10);
}
// stream 为集合创建串行流
numbers.stream ().forEach (n -> {
System.out.print (n + " ");// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
});
System.out.println ();
numbers.stream ().forEachOrdered (n -> {
System.out.print (n + " ");// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
});
System.out.println ();
// parallelStream 为集合创建并行流
numbers.parallelStream()
.forEach(n -> {
System.out.print (n + " ");// 12 14 13 11 10 16 17 15 19 3 6 4 18 2 5 7 9 8 1
});
System.out.println ();
numbers.parallelStream ().forEachOrdered (n -> {
System.out.print (n + " ");// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
});
System.out.println ("\r\n结束");
}
ArrayList的序列化和反序列化的分析
从源码中可以看出来elementData
是存储ArrayList
数据的数组,所以序列化ArrayList
数据就是序列化elementData
的数组中的数据。由于数组elementData
的空间有可能会有剩余,所以每次将ArrayList
的数据序列化时并不需要将整个数组elementData
的数组全部序列化,只需要将elementData[0..size]
数据序列化就行了。所以源码中用transient
修饰了数组elementData
,并自定义了writeObject
方法和readObject
方法,如下:
/**
* 将ArrayList实例保存到一个流中 (即序列化)。
*/
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 实例(即反序列化)
*/
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();
}
}
}
writeObject
方法和readObject
方法都用了private
的修饰符修饰了,那么实际序列化时又是如何实现的呢?我们可以使用下面这段测试代码,通过debug
去看看ArrayList
是怎么实现自定义序列化和反序列化的
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 输出流
ObjectOutputStream oos = new ObjectOutputStream(baos);
// 这个方法最终会调用ArrayList 中的writeObject() 方法
oos.writeObject(list);
byte[] alBytes = baos.toByteArray();
ArrayList<String> readList = null;
try {
// 输入流
readList = (ArrayList<String>) new ObjectInputStream(
new ByteArrayInputStream(alBytes)).readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
for (String s : readList) {
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}
先分析ArrayList
的序列化过程:通过debug
运行上面的测试代码,可以发现oos.writeObject(list);
这行代码会根据传进来的ArrayList
对象得到Class
,然后再包装成ObjectStreamClass
,在writeSerialData
方法里,会调用ObjectStreamClass
的invokeWriteObject
方法;在invokeWriteObject
方法里会调用Method
的invoke(Object obj, Object... args)
,通过反射调用到ArrayList
里的writeObject
方法。代码如下:
private void writeSerialData(Object obj, ObjectStreamClass desc)
throws IOException {
ObjectStreamClass.ClassDataSlot[] slots = desc.getClassDataLayout();
for (int i = 0; i < slots.length; i++) {
ObjectStreamClass slotDesc = slots[i].desc;
.....
slotDesc.invokeWriteObject(obj, this);
.....
}
}
/**
* 调用实现 serializable 接口类的writeObject方法。
**/
void invokeWriteObject(Object obj, ObjectOutputStream out)
throws IOException, UnsupportedOperationException {
requireInitialized();
if (writeObjectMethod != null) {
try {
// 通过反射访问到ArrayList 中的writeObject 方法
writeObjectMethod.invoke(obj, new Object[]{ out });
} catch (InvocationTargetException ex) {
Throwable th = ex.getTargetException();
if (th instanceof IOException) {
throw (IOException) th;
} else {
throwMiscException(th);
}
} catch (IllegalAccessException ex) {
// should not occur, as access checks have been suppressed
throw new InternalError(ex);
}
} else {
throw new UnsupportedOperationException();
}
}
writeObjectMethod
实例赋值的方式如下:
private static Method getPrivateMethod(Class<?> cl, String name,
Class<?>[] argTypes,
Class<?> returnType) {
try {
Method meth = cl.getDeclaredMethod(name, argTypes);
// 设置private 方法可以访问
meth.setAccessible(true);
int mods = meth.getModifiers();
return ((meth.getReturnType() == returnType) &&
((mods & Modifier.STATIC) == 0) &&
((mods & Modifier.PRIVATE) != 0)) ? meth : null;
} catch (NoSuchMethodException ex) {
return null;
}
}
上面是对ArrayList
序列化的过程分析,反序列化的过程是调用readObject
方法和序列化一样。