1. 类结构
public class ArrayList extends AbstractList implements List, RandomAccess, Cloneable, java.io.Serializable
1.1 实现接口
1.1.1 RandmoAccess接口:
是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问
想详细了解的呢可以看RandomAccess接口的使用
1.1.2 Cloneable接口:
即覆盖了函数clone(),能被克隆
1.1.3 Serializable接口
意味着ArrayList支持序列化,能通过序列化去传输
1.1.4 List接口:
在Java集合分类中,List代表有序,可重复
具体和下面父类一起说
1.2 父类AbstractList
ArrayList 继承了AbstractList,父类也实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能
1.3 它跟数组的关系?
1.3.1数组VS链表
Array(数组),数据结构适合内存结构也是连续的(适合遍历),随机访问(适合查找),不适合增删(链表则相反),同时在创建数组的同时你必须指定大小
想知道详细的可以看看数组与链表的优缺点
1.3.2 数组 VS ArrayList
- Array类型的变量在声明的同时必须进行实例化(至少得初始化数组的大小),而ArrayList可以只是先声明。
- Array只能存储同构的对象,而ArrayList可以存储异构的对象。
List内部就是使用”object[] _items;”这样一个私有字段来封装对象的) - 在CLR托管对中的存放方式:
Array是始终是连续存放的,而ArrayList的存放不一定连续。 - 初始化大小:
Array对象的初始化必须只定指定大小,且创建后的数组大小是固定的,
而ArrayList的大小可以动态指定,其大小可以在初始化时指定,也可以不指定,也就是说该对象的空间可以任意增加。 - Array不能够随意添加和删除其中的项,而ArrayList可以在任意位置插入和删除项。
同构和异构:
同构的对象是指类型相同的对象,若声明为int[]的数组就只能存放整形数据,string[]只能存放字符型数据,但声明为object[]的数组除外。
而ArrayList可以存放任何不同类型的数据(因为它里面存放的都是被装箱了的Object型对象,实际上Array
回到正文了,去看看ArrayList源码罗
2. 探索源码
2.1 构造
// ArrayList带容量大小的构造函数。
public ArrayList(int initialCapacity) {
super();
if (initialCapacity
2.2添加
/**
* 添加一个元素
*/
public boolean add(E e) {
// 进行扩容检查
ensureCapacity( size + 1); // Increments modCount
// 将e增加至list的数据尾部,容量+1
elementData[size ++] = e;
return true;
}
/**
* 在指定位置添加一个元素
*/
public void add(int index, E element) {
// 判断索引是否越界,这里会抛出多么熟悉的异常。。。
if (index > size || index
2.3 删除
/**
* 根据索引位置删除元素
*/
public E remove( int index) {
// 数组越界检查
RangeCheck(index);
modCount++;
// 取出要删除位置的元素,供返回使用
E oldValue = (E) elementData[index];
// 计算数组要复制的数量
int numMoved = size - index - 1;
// 数组复制,就是将index之后的元素往前移动一个位置
if (numMoved > 0)
System. arraycopy(elementData, index+1, elementData, index,
numMoved);
// 将数组最后一个元素置空(因为删除了一个元素,然后index后面的元素都向前移动了,所以最后一个就没用了),好让gc尽快回收
// 不要忘了size减一
elementData[--size ] = null; // Let gc do its work
return oldValue;
}
/**
* 根据元素内容删除,只删除匹配的第一个
*/
public boolean remove(Object o) {
// 对要删除的元素进行null判断
// 对数据元素进行遍历查找,知道找到第一个要删除的元素,删除后进行返回,如果要删除的元素正好是最后一个那就惨了,时间复杂度可达O(n) 。。。
if (o == null) {
for (int index = 0; index
2.4 更新
/**
* 将指定位置的元素更新为新元素
*/
public E set( int index, E element) {
// 数组越界检查
RangeCheck(index);
// 取出要更新位置的元素,供返回使用
E oldValue = (E) elementData[index];
// 将该位置赋值为行的元素
elementData[index] = element;
// 返回旧元素
return oldValue;
}
2.5查找
/**
* 查找指定位置上的元素
*/
public E get( int index) {
RangeCheck(index);
return (E) elementData [index];
}
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i
3. ArrayList3种遍历方式
(01) 第一种,通过迭代器遍历。即通过Iterator去遍历。
Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}
(02) 第二种,随机访问,通过索引值去遍历。
由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。
Integer value = null; int size = list.size(); for (int i=0; i
4 总结
ArrayList和LinkedList的区别
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
- 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
- 对于新增和删除操作add和remove,LinkedList比较占优势,因为ArrayList要移动数据。
ArrayList和Vector的区别
- Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同步类。因此开销就比ArrayList要大,访问要慢。正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。
- Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。
- Vector还有一个子类Stack.