简介
ArrayList就是动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了动态的增加和减少元素,实现了ICollection和IList接口,灵活的设置数组的大小等好处
有图有码
图为手工画的,有点丑见谅 _!
初始化集合ArrayList list = new ArrayList(); 因为使用无参构造时候集合容器为空,所以无任何空位。第一次添加元素 add("a") 第一次添加元素时候,检测容器为空,根据默认容量10进行初始化容器。然后将元素放置到第一个空位中。 初始化容器: 增加一个元素:第十一次添加元素 add("k") 第十一次添加元素,发现元素超出容量,所以进行一次扩容,扩容后的大小为原容量加原容量的二分之一,即为15;然后将元素放置到第是一个空位中。 增加容量: 增加一个元素:移除期中一个元素 remove(3) 移除第三个元素,将数组从第四个元素到最后一个元素放置到第三个元素开始到最后,然后将数组的最后一位元素设为null。
源码分析
构造方法
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;
private static final int DEFAULT_CAPACITY =
10;
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public ArrayList(int initialCapacity) {
if (initialCapacity >
0) {
this.elementData =
new Object[initialCapacity];
}
else if (initialCapacity ==
0) {
this.elementData = EMPTY_ELEMENTDATA;
}
else {
throw new IllegalArgumentException(
"Illegal Capacity: "+
initialCapacity);
}
}
public ArrayList(Collection<?
extends E> c) {
elementData = c.toArray();
if ((
size = elementData.length) !=
0) {
if (elementData.getClass() != Object[].
class)
elementData = Arrays.copyOf(elementData,
size, Object[].
class);
}
else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
方法及源码
add
public boolean add(E e) {
ensureCapacityInternal(
size +
1);
elementData[
size++] = e;
return true;
}
public void add(
int index, E element) {
rangeCheckForAdd(
index);
ensureCapacityInternal(size +
1);
System.arraycopy(elementData,
index, elementData,
index +
1,
size -
index);
elementData[
index] = element;
size++;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
if (minCapacity - elementData.length >
0)
grow(minCapacity);
}
private void grow(int minCapacity) {
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >>
1);
if (newCapacity - minCapacity <
0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE >
0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity <
0)
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
remove
public boolean remove(Object o) {
if (o ==
null) {
for (
int index =
0;
index < size;
index++)
if (elementData[
index] ==
null) {
fastRemove(
index);
return true;
}
}
else {
for (
int index =
0;
index < size;
index++)
if (o.equals(elementData[
index])) {
fastRemove(
index);
return true;
}
}
return false;
}
public E remove(
int index) {
rangeCheck(
index);
modCount++;
E oldValue = elementData(
index);
int numMoved = size -
index -
1;
if (numMoved >
0)
System.arraycopy(elementData,
index+
1, elementData,
index,
numMoved);
elementData[--size] =
null;
return oldValue;
}
private void fastRemove(
int index) {
modCount++;
int numMoved = size -
index -
1;
if (numMoved >
0)
System.arraycopy(elementData,
index+
1, elementData,
index,
numMoved);
elementData[--size] =
null;
}
get
public E get(
int index) {
rangeCheck(
index);
return elementData(
index);
}
set
public E set(
int index, E element) {
rangeCheck(
index);
E oldValue = elementData(
index);
elementData[
index] = element;
return oldValue;
}
clear
public void clear() {
modCount++;
for (
int i =
0; i <
size; i++)
elementData[i] =
null;
size =
0;
}
总结
通过源码分析,ArrayList集合就是通过System.arraycopy方法将普通数组Object[]包装为一个动态数组,实现数组的增删改查。
优点 1、修改元素和通过下标查询元素效率高 2、集合是有顺序的缺点 1、删除元素效率低,因为要通过拷贝数组来实现 2、大量新增效率低,因为大量新增的时候要不断进行扩容和数组的拷贝 3、清除集合效率低,因为清除功能是通过循环数组进行清除的 4、移除元素后,容量有大量剩余,需要手动调用trimToSize进行清理
其他
1、使用时候如果知道预期容量,建议设定容量,避免不断扩容影响效率。 2、建议改进清除操作,避免使用循环进行清除。
参考
百度百科 http://baike.baidu.com/link?url=Ff4TnTpO2FNkD2y4Z0VuM_caPtYUkV74O4f-rFnXB_kvu-KA8FlttknMy481CwO2XcN1nfhZHqk7UAnBKVMOgki5rB3WlfLvxZHuJktz8gu
由ArrayList构造函数源码引出的问题 http://www.cnblogs.com/zhizhizhiyuan/p/3662371.html