有序数组,元素必须是应用类型,不能是基本类型,即存储的是对象在堆内存中位置;值可为null;线程不安全 。
1. 遍历问题:
* 迭代器遍历:
ArrayList 使用一个int变量 modCount 记录结构变更次数,结构变更包含: 增、删、扩容、截断、排序、清除,每变更一次 modCount 加1;
```
/**
* The number of times this list has been <i>structurally modified</i>.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
* ......
*/
protected transient int modCount = 0;
```
ArrayList 迭代器 实例化时拷贝modCount的值到expectModCount中, next、remove、forEachRemaining 方法 执行时均会校验 modCount != expecteModCount , 不一致将抛出 ConcurrentModificationException 。可避免在使用过程中出现ArrayList 结构变更读取到脏数据的情况,但无法防止ArrayList 中元素属性(如元素Interger 值) 发生变化 ,即保证的对象指针不可变(数量、内容不变),对象属性不能保证。
其中强化版的for(item :list)底层也是使用迭代器,情况同上 ;
* 普通for遍历:
普通for 不会抛ConcurrentModificationException 异常,但有可能出现数组越界,无法识别出遍历时 ArrayList 被修改的情况。
2. 线程安全:
ArrayList 是非线程安全的。但可通过集合工具类包装出线程安全的实例:
`List<Integer> listInt = Collections.synchronizedList(new ArrayList<>());`
此线程安全实例只在 增、删等操作下加锁,比线程安全的Vector更轻量,有效率优势;
在 迭代器中无效,因而在迭代器遍历时需主动加 synchronized 保证线程安全
```
synchronized (listInt){
Iterator it = listInt.iterator();
while (it.hasNext()){
it.next();
}
}
```
3. clone-浅复制:
ArrayList 的克隆只复制对象地址,不复制对象。clone 对象删除动作只是移除引用,不会删除对象 。新旧两个ArrayList均指向同一个对象。如果希望不相互影响,需要用ArrayList 元素对象的克隆。