ArrayList(jdk 1.7.0_80)
jdk1.7中有几个更新,List<Integer> l = new ArrayList();是允许的,更多的jdk1.7特性可参考:陈大大博客 http://blog.csdn.net/chenleixing/article/details/47802653。
看源码,
1 public class ArrayList<E> extends AbstractList<E> 2 implements List<E>, RandomAccess, Cloneable, java.io.Serializable 3 { 4 ... 5 }
ArrayList类继承AbstractList抽象类,实现List接口randomAccess、Cloneable、Serializable接口。这里列出接口源码是为之后分析List各个实现类之间的区别。也是提倡看源代码,看里面的代码结构和实现思路。
1 public ArrayList(int initialCapacity) { 2 super(); 3 if (initialCapacity < 0) 4 throw new IllegalArgumentException("Illegal Capacity: "+ 5 initialCapacity); 6 this.elementData = new Object[initialCapacity]; 7 }
无参构造方法
1 public ArrayList() { 2 super(); 3 this.elementData = EMPTY_ELEMENTDATA; 4 }
1.ArrayList的构造方法,初始化有个DEFAULT_CAPACITY = 10;如果用无参构造方法,那么就是创建一个容量为10的ArrayList。装数据的对象是elementData,他是一个数组。数组的特点:易于查找,不便大批量插入数据和删除数据。
2.add() **要注意看墨绿色 的注释,很容易就能看懂源码思路。
1 public boolean add(E e) { 2 ensureCapacityInternal(size + 1); // Increments modCount!! 3 elementData[size++] = e; 4 return true; 5 }
E 类型是底层jdk中定义的一种类型,元素类型,
第一步 ensureCapacityInternal(size+1); 作用是确保数组的大小足够大,能够放入这个e元素,这里做的就是size扩大1。先贴出源码,再细细分析他做了什么。
1 private void ensureCapacityInternal(int minCapacity) { 2 if (elementData == EMPTY_ELEMENTDATA) {//如果为空elementData,则取默认容量大小和传入参数之间的最大的 3 minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); 4 } 5 6 ensureExplicitCapacity(minCapacity);//创建数组对象,并让大小满足要求 7 } 8 9 private void ensureExplicitCapacity(int minCapacity) {//modecount记录操作结构的次数,即你每扩大一次数组大小就记录一次。 10 modCount++;//modCount = modCount+1 11 12 // overflow-conscious code 13 if (minCapacity - elementData.length > 0)//如果要求的容积大于现在的大小,那么执行grow操作。 14 grow(minCapacity); 15 } 16 17 private void grow(int minCapacity) { 18 // overflow-conscious code 溢栈情况 19 int oldCapacity = elementData.length; 20 int newCapacity = oldCapacity + (oldCapacity >> 1);//扩大原来的一般,即1.5倍后 21 if (newCapacity - minCapacity < 0)//如果扩大1.5倍任然小于需要的大小,那么赋值 22 newCapacity = minCapacity; 23 if (newCapacity - MAX_ARRAY_SIZE > 0) 24 newCapacity = hugeCapacity(minCapacity); 25 // minCapacity is usually close to size, so this is a win: 26 elementData = Arrays.copyOf(elementData, newCapacity);//Arrays.copyOf()方法 27 }
这里Arrays.copyOf()方法将原来的elelmentData对象数据转移到另一个newCapacity大小的数组中,那么就实现了扩容的效果。最后将值放到size+1位置处。然后返回true,增加成功。
ArrayList的add方法是相对简单的,在Map中的添加方法put方法会复杂些。
3.get(int i)
1 public E get(int index) { 2 return a[index]; 3 }
比较容易理解,直接返回数组中位于index位置处的值。
这里再讲一下迭代器Iterator,用法就是new一个Iterator对象,将ArrayList对象作为参数传入。然后不用for(int i =list;;){}其实迭代器做的功能就是循环输出list中的每个元素。
ArrayList允许传入的是null,可以保存null。可以传入重复的值。保存的值是有序的,因为是序列,所以都是有序的。线程不安全,这里带过就可以了。
**空重序安。按照这个顺序记是没错的。
然后讲一下,为什么要在elementData前加transient字段。
在序列化对象的时候,可能数组不是满,数组的大小是10,而只有三个位置是有值的,如果全部序列化会太浪费资源和时间,这里就用到了一个方法,将elementData中的数据取出,并序列化,不去序列化所有。具体实现是重写writeObject()方法实现的。
不便将所有源码都贴出来,自己去看看吧。
ArrayList与LinkedList之间的比较就放之后讲吧。