1、通过Object类型的数组来实现,所以数组中需要存储基本类型数据的时候需要使用包装类
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L;
/**
* Default initial capacity.
*/
private static final int DEFAULT_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
2、初始化的无参构造函数为一个空对象数组,在添加第一个元素的时候,会默认申请10个大小的内存空间,如果添加到了尾端,在进行1.5倍的空间申请并将原来存储的数据挪动复制到新申请的内存空间中
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
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);
}
3、数组在遍历的时候很快就是因为内存地址是连续的,所以查找某个位置的元素可以瞬间获取到,所以遍历的是特别快的,通过第一个元素的地址就能计算出后面第N位的元素地址
4、ArrayList实现了一个叫RandomAccess的空接口,实际上实现这个接口只是为了做打标,就是告诉别人当前的这个类支持快速访问,所以在进行泛型对象的遍历的时候,由于我们不清楚具体的实现类是什么,所以可以判断是否实现了RandomAccess接口,如果实现了此接口则进行for循环遍历集合,否之则使用迭代器,所以这里的RandomAccess就是为了告诉别人当前实现类支持快速访问,但实际上是否能快速访问还是因为存储的数据结构不一样
public static void loop(java.util.List list){
if(list instanceof RandomAccess) {
// for循环
System.out.println("采用for循环遍历");
for (int i = 0;i< list.size();i++) {
System.out.println(list.get(i));
}
} else {
// 迭代器
System.out.println("采用迭代器遍历");
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
public static void main(String[] args) {
java.util.List<String> list = Arrays.asList("123","456","789","1110");
java.util.List<String> list1 = new LinkedList<>();
list1.add("aaa");
list1.add("bbb");
list1.add("ccc");
loop(list);
loop(list1);
}
5、ArrayList中的存储数组elementData是用transient修饰的,而ArrayList又是实现了Serializable接口表明是可实例化的,这里就是很矛盾,因为被transient修饰的数据是不会被实例化的。实际上是因为刚刚说的数组的空间是必须要提前申请的,所以这里有个问题就是数组可能会空间比较大,但实际上存储的元素没有那么多。所以在序列化的时候完全不需要去序列化那些空内存,所以ArrayList手动实现了序列化方法,根据元素的多少进行序列化。
/**
* 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
/**
* Save the state of the <tt>ArrayList</tt> instance to a stream (that
* is, serialize it).
*
* @serialData The length of the array backing the <tt>ArrayList</tt>
* instance is emitted (int), followed by all of its elements
* (each an <tt>Object</tt>) in the proper order.
*/
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();
}
}
/**
* Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
* deserialize it).
*/
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();
}
}
}