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之间的比较就放之后讲吧。

 
原文地址:https://www.cnblogs.com/bamaofan/p/5788807.html