ArrayList :
1.实现List接口,查询速度快,插入删除较慢(相对LinkedList);
2.底层数据结构为数组,动态数组,即容量可根据情况自动增长
3.线程不安全,多线程情况下可以考虑Collections.synchronizedList(list 1)返回一个线程安全的ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
由于实现了Serializable接口,因此可以序列化,用于网络传输,RandomAccess接口,支持快速随机访问,即通过下标序号进行快速访问,实现了cloneable接口,可被克隆.
ArrayList在扩容时候,不同步,当多个线程同时访问一个ArrayList实例时,其中一个线程从结构修改了列表(数组结构大小变更),则外部必须保持同步(可以加个synchronize)
组成部分:
1.两个私有属性
transient Object[] elementData;//数据存放位置
transient int size;//ArrayList的大小
transient :当持久化对象时,当有一个我们不想Serialization机制保存时,为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上此关键字.比如传递用户User时,修饰Password,传输接收后没有Password数据
2.构造方法
ArrayList包含了三种方式的构造器,可以构造一个默认初始化容量为null的空列表,构造一个指定初始容量的空列表以及构造一个包含指定collection的元素的列表,元素按照该collection的迭代器返回它们的顺序排列.
A. 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);
}
}
B. public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }
C.
public ArrayList(Collection<? extends E> 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;
}
}
存储元素:
ArrayList 提供了set(int index,E element) ,add(E e) ,add(int index,E element),addAll(Collection<? extends E> c),addAll(int index,Collection<? extends E> c)
ArrayList扩容关键代码:
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; 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); }
由代码可看出新的数组大小为 int newCapacity = oldCapacity + (oldCapacity >> 1);// 旧大小右移一位
补充:
<< : 左移运算符,num << 1,相当于num乘以2
>> : 右移运算符,num >> 1,相当于num除以2
>>> : 无符号右移,忽略符号位,空位都以0补齐
Fail-Fast机制:类似HashMap 线程不安全保护机制
我们知道java.util.ArrList不是线程安全的,因此如果在使用迭代器的过程中有其他线程修改了ArrList,那么将抛出ConcurrentModificationException,这就是所谓fail-fast策略。
这一策略在源码中的实现是通过modCount域,modCount顾名思义就是修改次数,对ArrList内容的修改都将增加这个值,那么在迭代器初始化过程中会将这个值赋给迭代器的expectedModCount。
在迭代过程中,判断modCount跟expectedModCount是否相等,如果不相等就表示已经有其他线程修改了ArrayList:
注意到modCount声明为volatile,保证线程之间修改的可见性。