1.ArrayList的特点:
线程不安全
查找速度快
增删速度慢
数组结构
ArrayList源码分析:
2.ArrayList的继承和实现接口关系
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
可以看到ArrayList继承了AbstractList<E>类,实现了implements List<E>, RandomAccess, Cloneable, java.io.Serializable接口;
AbstractList<E>类的继承实现关系如下了public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> ,AbstractList<E>继承了AbstractCollection类,查看AbstractList<E>类的源码,我们可以发现
AbstractList<E>实现了部分的方法,又有一部分的方法是抽象的方法;
当我们看AbstractCollection<E> 源码的时候,可以发现public abstract class AbstractCollection<E> implements Collection<E>,终于AbstractCollection<E> 实现了Collection<E>接口,ArrayList和Collection<E>终于挂上关系了,
AbstractCollection<E> 也实现了部分方法,有部分方法是抽象方法。
从这么多继承和实现关系,可以看出这些类的实现都是分层的,那个类做什么事情。
由于ArrayList类的方法众多,我就不每个都介绍了,下面主要介绍下常用的方法和属性。想理解更多地可以直接看源代码,有很清楚的介绍
3.ArrayList的基本属性
private static final long serialVersionUID = 8683452581122892189L;//序列化的标志
private static final int DEFAULT_CAPACITY = 10;//Default initial capacity.即默认初始化的ArrayList的大小
private static final Object[] EMPTY_ELEMENTDATA = {};//共享空数组实例用于空实例
private transient Object[] elementData;//数组缓冲区存储数组列表的元素,存储元素的数组
private int size;//数组元素的大小
4.ArrayList的构造方法
初始化指定大小的列表,初始化大小为initialCapacity,如果参数小于0则会抛出参数非法异常,如果参数大于0,则创建指定大小的Object数组,使elementData元素指向数组
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
初始化ArrayList里面的elementData,利用一个空的Object数组初始化EMPTY_ELEMENTDATA
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}
使用指定的集合初始化列表,列表的长度就是集合元素c的长度,及集合c的数据元素的个数
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
elementData = Arrays.copyOf(elementData, size, Object[].class);//这一句是进行数组的复制
5.ArrayList常用的方法
//将此 ArrayList 实例的容量调整为列表的当前大小,去掉列表中多余的空间,
public void trimToSize() {
modCount++;
if (size < elementData.length) {//如果目前的元素个数小于elementData的空间个数,即有多余的空间浪费了没有使用
elementData = Arrays.copyOf(elementData, size);//进行数组的复制,去掉多余的空间
}
}
//如果有必要的话,增加列表空间的大小,确保列表能够存放下元素
public void ensureCapacity(int minCapacity) {
//最小的扩张列表的大小
int minExpand = (elementData != EMPTY_ELEMENTDATA)//如果elementData不等于EMPTY_ELEMENTDATA
// any size if real element table
? 0
// larger than default for empty table. It's already supposed to be
// at default size.
: DEFAULT_CAPACITY;//默认的大小及定义的10
//如果最小的空间长度大于最小规定的扩展长度则进行扩展
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
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);
}返回列表元素的长度
public int size() {
return size;
}判断是否为空
public boolean isEmpty() {
return size == 0;
}
//从前到后依次查找元素在集合中第一次出现的下标,如果找到了则返回下标,没有则返回-1
public int indexOf(Object o) {
if (o == null) {//如果元素为null
for (int i = 0; i < size; i++)
if (elementData[i]==null)//如果列表中存在为null的元素,则返回下标
return i;//返回下标
} else {//如果元素o不为null
for (int i = 0; i < size; i++)//进行顺序查找
if (o.equals(elementData[i]))//进行判断,如果存在相等,则返回下标i
return i;//返回下标
}
return -1;//没有查找到,则返回-1
}
//进行判断,元素o是否存在于列表中
public boolean contains(Object o) {
//如果查找到了,则返回true,没有查找到则返回false
return indexOf(o) >= 0;//返回结果
}
//从后向前依次查找元素在集合中第一次出现的下标,如果找到了则返回下标,没有则返回-1
public int lastIndexOf(Object o) {
if (o == null) {//如果元素为null
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)//如果列表中存在为null的元素,则返回下标
return i;//返回下标
} else {
for (int i = size-1; i >= 0; i--)//进行顺序查找
if (o.equals(elementData[i]))//进行判断,如果存在相等,则返回下标i
return i;//返回下标
}
return -1;//没有查找到,则返回-1
}
//把列表转换成数组进行返回
public Object[] toArray() {
return Arrays.copyOf(elementData, size);//数组进行复制,返回复制后的数组
}
//返回集合中包含的数组a的所有元素
public <T> T[] toArray(T[] a) {
if (a.length < size)//如果数组a长度小于列表的长度,则直接把列表前size个元素复制给a数组
// Make a new array of a's runtime type, but my contents:
return (T[]) Arrays.copyOf(elementData, size, a.getClass());//返回复制后的结果
System.arraycopy(elementData, 0, a, 0, size);//如果数组a的长度大于列表的长度,则把列表从0到size的元素复制给a数组
if (a.length > size)//如果a的长度大于size,则a数组有值的最后一个空的空间置位null
a[size] = null;
return a;//返回a数组
}
//得到指定位置的元素
public E get(int index) {
rangeCheck(index);//进行参数的检查,看是否在可控的范围内
return elementData(index);//返回指定下标的元素
}
//把更改指定位置的值
public E set(int index, E element) {
rangeCheck(index);//进行参数的检查
E oldValue = elementData(index);//得到改变前指定位置的元素
elementData[index] = element;//在指定的位置设置新的值
return oldValue;//返回指定位置改变前的值,即老得值
}
//在列表的末尾添加元素
public boolean add(E e) {
//进行空间的检查,看空间是否够存入新的元素,不够的话进行分配新的空间
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;//把元素放到列表的最后,元素的个数size加1
return true;//元素添加成功后,返回true
}
//在指定的位置插入元素
public void add(int index, E element) {
rangeCheckForAdd(index);//检查参数index范围
//确保空间足够添加元素
ensureCapacityInternal(size + 1); // Increments modCount!!
//进行数组元素的复制操作,把index以后的所有元素往后移动一个位置
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;//在index位置插入元素element
size++;//列表元素的个数加1
}
//删除指定位置的元素
public E remove(int index) {
rangeCheck(index);//参数检查
modCount++;
E oldValue = elementData(index);//得到删除前指定位置的元素
int numMoved = size - index - 1;//计算需要复制的长度
if (numMoved > 0)//如果长度大于0,则进行复制,即把index后的元素依次前移一个位置
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;//返回指定位置删除的元素
}
//删除指定的元素o
public boolean remove(Object o) {
if (o == null) {//如果元素o为空
for (int index = 0; index < size; index++)//顺序查找是否存在为null的元素
if (elementData[index] == null) {//如果为null
fastRemove(index);//进行快速删除
return true;//返回结果
}
} else {//如果元素o不为空
for (int index = 0; index < size; index++)//进行查找
if (o.equals(elementData[index])) {//如果找到了与元素o相等的元素
fastRemove(index);进行快速删除
return true;//返回结果true
}
}
return false;//返回结果false
}
//私有的方法,进行快速的删除操作,删除指定的位置元素index
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;//需要移动元素的长度
if (numMoved > 0)//如果移动的长度数量大于0
System.arraycopy(elementData, index+1, elementData, index,
numMoved);//进行移动复制
//元素数量减一,最后一个元素置为null
elementData[--size] = null; // clear to let GC do its work
}
//清空列表中所有的元索
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)//进行循环,把所有的元素置位null
elementData[i] = null;//把元素置位null
size = 0;//列表的大小置位0
}
//把一个集合的元素添加到列表中
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();//把集合转换成Object数组
int numNew = a.length;//得到Object数组的大小
//看是否需要开辟空间,需要则进行开辟新的空间
ensureCapacityInternal(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);//进行数组的复制
size += numNew;//列表元素的长度变了
return numNew != 0;//添加完成以后的返回值
}
//从指定的位置开始,把一个集合添加到列表中
public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);//index下标检查
Object[] a = c.toArray();//转换成数组
int numNew = a.length;//得到长度
//开辟空间
ensureCapacityInternal(size + numNew); // Increments modCount
int numMoved = size - index;//得到需要移动的长度
if (numMoved > 0)//如果移动的长度大于0
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);//进行数组移动的复制
System.arraycopy(a, 0, elementData, index, numNew);//数组的复制
size += numNew;//列表元素长度增加
return numNew != 0;//返回添加的结果
}
//删除列表中指定范围的元素
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);//进行复制
// clear to let GC do its work
int newSize = size - (toIndex-fromIndex);
for (int i = newSize; i < size; i++) {
elementData[i] = null;//置位null
}
size = newSize;//列表中新的元素的长度
}
原文地址:http://blog.csdn.net/j903829182/article/details/38498523