ArrayList 是Java中最常见的几大类之一,也是最主要的集合类之一。
一、官方的介绍
可调整大小的数组。包含所有可选列表的操作。并允许所有元素,包括null。除了实现 List 接口之外,这个类提供了操作数组大小的方法用于内部存储列表。(这个类大致相当于Vector,但它是非同步的。)
size,isempty,get,set,iterator,和 listiterator 操作在常量运行
时间。add 操作在摊销常量时间内运行,也就是说,添加n个元素需要的时间是O(n)。所有其他操作在线性时间内运行(大致来说)。常数因子比linkedlist要低。
每个ArrayList实例都有一个容量。容量是用于存储列表中元素的数组的大小。总是这样至少和列表大小一样大。当元素被添加到ArrayList时,它的容量自动增长。增长政策的细节不是在添加一个元素有常数摊销的事实之外指定时间成本。
程序可以在使用 ensurecapacity 添加大量元素之前进行对 ArrayList 实例的扩容操作。这可能会减少增量重新分配的数量。
请注意,此实现不同步。
如果多个线程同时访问 ArrayList 实例,至少有一个线程在结构上修改了列表,那它必须要在外部同步。(结构修改是任何添加或删除一个或多个元素的操作,或显式地调整后备数组的大小)仅设置元素的值不是这通常是通过在自然封装列表的某个对象上进行同步。如果不存在这样的对象,则应该使用collections \ synchronizedlist \ collections.synchronizedlist 方法。最好在创建时完成,以防止意外对列表的非同步访问:
List list = Collections.synchronizedList(new ArrayList(...));
这个类的 iterator() 返回的迭代器和listiterator方法是快速失败的: 如果在迭代器以任何方式创建,除了通过迭代器自己的 listiterator remove()或 add方法,迭代器将抛出ConcurrentModificationException。因此,面对 并发修改时,迭代器会快速而干净地失败,而不是 而不是冒着任意的、不确定的行为 未来的时间。
注意,不能保证迭代器的快速失败行为 一般说来,在 存在未同步的并发修改。失效快速迭代器 尽最大努力抛出{@code concurrentmodificationexception}。 因此,编写依赖于此的程序是错误的 正确性异常:迭代器的快速失败行为 只用于检测错误。
二、属性源码
/**
* Default initial capacity.
*/private static final intDEFAULT_CAPACITY= 10;
/**
* Shared empty array instance used for empty instances.
*/private static final Object[]EMPTY_ELEMENTDATA= {};
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/private static final Object[]DEFAULTCAPACITY_EMPTY_ELEMENTDATA= {};
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
* will be expanded to DEFAULT_CAPACITY when the first element is added.
*/transient Object[] elementData;
// non-private to simplify nested class access
/**
* The size of the ArrayList (the number of elements it contains).
*
* @serial*/private int size;
其中:
int DEFAULT_CAPCITY = 10; // 默认初使化长度为 10
Object[] EMPTY_ELEMENTDATA = {};
Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // 数组缓冲区
int size; //数组大小
而其中的 elementData 为了简化嵌套类的访问,而没有使用 private 关键字。但并不意味着就可以直接访问了。
transient 关键字表示这个变量将不是对象持久化的一部分,也就意味着 序列化时,该数据不会被序列化。相对应的,反序列化时也无法得到该值。
其中不太好理解的是 这里面有两个空数组。
EMPTY_ELEMENTDATA 和 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
实际上,这俩个只在构造时使用,如果命使用的是 无参构造函数,那就会使
elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
而如果用的是 new ArrayList(0); 那么就会是
elementData = EMPTY_ELEMENTDATA;
三、构造函数
/**
* Constructs an empty list with the specified initial capacity.
*
*@paraminitialCapacity the initial capacity of the list
*@throwsIllegalArgumentException if the specified initial capacity
* is negative
*/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);
}
}
/**
* Constructs an empty list with an initial capacity of ten.
*/public ArrayList() {
this.elementData =DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
*@paramc the collection whose elements are to be placed into this list
*@throwsNullPointerException if the specified collection is null
*/public ArrayList(Collection extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData =EMPTY_ELEMENTDATA;
}
}
由源码可以看到,ArrayList 共有三个构造函数
ArrayList ( )
ArrayList ( int initialCapacity )
ArrayList ( Collection extends E> c )
前俩个都比较简单
第三个的介绍如下
构造一个包含指定集合的元素的列表,按集合的迭代器返回这些元素的顺序。
简单说,就是复制一个 实现 Collenction 接口的 集合。
而复制所使用的是 Arrays.copyOf 方法。
同样值得注意的是,该构造方法会抛出空指针异常,在使用的时候要小心。
下一篇开始读 ArrayList 的方法