自我学习源码,也借鉴了网上其他的资料,有写的不准确的地方,请轻喷,谢谢
1.位于Java.util包下
2.继承关系
1)继承自AbstractList类
2)
实现了RandomAccess接口,RandomAccess接口是List 实现所使用的标记接口,用来表明其支持快速(通常是固
定时间)随机访问。
此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提
供良好的性能。
在对List特别的遍历算法中,要尽量来判断是属于RandomAccess(如ArrayList)还是
SequenceAccess(如LinkedList),
因为适RandomAccess List的遍历算法,用在SequenceAccess List上就差别
很大,即对于实现了RandomAccess接口的类实例而言,
此循环
for (int i=0, i<list.size(); i++)
list.get(i);
的运行速度要快于以下循环:
for (Iterator i=list.iterator(); i.hasNext(); )
i.next();
3)实现了Cloneable接口,也是标记接口。
4)实现了Serializable接口,也是标记接口。
3.底层是用数组实现的,所以查找的效率比LinkedList高,支持随机访问
4.ArrayList有一个默认容量,且容量大小是自动变化的,以满足放入的内容的个数。
容量默认大小是10(从jdk1.2开始),并且有新元素加入时,即调用add()后,会调用ensureCapacityInternal(int size)来维护数组的大小,
在ensureCapacityInternal(int size)中当加入这个元素后如果容量大于当前的容量,则会调用grow()来新建一个新的数组,并将之前的数据拷贝到这个新数组中。
新数组的容量默认是按照原来数组的1.5倍大小增加
5.ArrayList的属性
注意:size不一定等于elementData.length,只有当size>elementData.length时才会调用grow()
6.ArrayList的构造函数
1)
无参的构造函数,将空的数组赋给ArrayList对象的属性elementData。
2)
带参数的构造函数,参数为初始化的容量,如果参数小于0,则会抛参数不合法的异常,如果大于等于0,则会创建Object数组赋给ArrayList对象的属性elementData。
3)
这个构造函数通过其他集合类对象来构造ArrayList对象,调用Arrays的静态方法copyOf(这个方法会调用底层的本地方法)来构造ArrayList对象。
7.当修改ArrayList结构后,会引发的问题
说明:结构改变包括:添加add(E),add(,int,E)、删除元素remove(int),remove(Object)等,或者明确的手动修改数组大小。如果仅仅的是给一个元素赋值,不属于结构的改变。
结构改变有可能会引发的问题:可能会导致Iterator报ConcurrentModificationException异常。
原因:当ArrayList使用了iterator()方法产生自身对应的Iterator来对数组链表的一些操作,都会通过checkForComodification()来判断当前获得iterator之后,数组链表是否没有通过这个iterator来操作
自身,而是通过自身的增加删除方法来操作。
8.Vertor与ArrayList的异同(在Vector中介绍)
9.ArrayList与LinkedList的异同(在LinkedList中介绍)
10.ArrayList是线程不安全的,所以效率比Vector高,要想变得线程安全,则
List list = Collections.synchronizedList(new ArrayList(...));
**一个问题:如源码所示,AbstractList已经实现了List接口了,但是在ArrayList还是再次的实现了List接口,这是为什么?
解答:当然这是没必要写的,把它去掉也没什么大的问题,不过写了的话,应该有原因的,可以这么想:
1.这么做,当我们查看ArrayList文档来了解这个类的继承关系,变得一目了然,不需要在文档或者IDE中点击查看;
2.这么做更明确,更加强调了这个类实现了List接口;
3.向后兼容性,如果哪天这个ArrayList不再实现List接口了,则ArrayList肯定实现List接口,并不会改变。