您的位置:首页 > 其它

ArrayList 源码分析

2012-11-03 13:10 363 查看
在我们刚学Java时老师一定会说ArrayList是很好用的变长数组,你只要尽管插入删除就可以了,比C++的数组控制简单多了,

ArrayList是典型的自增长数组。

private int size; //数组中实际元素的数量

capacity表示数组的总大小,比如arr = new int[5],则capacity=5.

//initialCapacity为初始的数组大小,因为自增长数组的缺点就是重新分配数组时会耗费内存,

重新分配就意味着原空间的垃圾生成加重垃圾回收的负担,

因此如果一开始分配的大一点,以后就会避免重新分配的次数

比如你如果要插入200个元素,则:

(1)一开始就分配200个元素的capacity,则一次分配

(2)一开始分配1个,不够了再多分配1个,如果没有垃圾回收,则1+2+3+......200=20100个空间

200和20100,差别很大吧。

先回顾下ArrayList中最核心的两个语句:

int[]newarr = Arrays.copyOf(int[]old,int newlength);

//newarr = Arrays.copyOf(oldarr,newlength);

//表示将oldarr的全部内容复制到newarr中,newarr的长度为newlength

System.arraycopy(oldarr, oldbegin, newarr, newbegin,length);

//将oldarr中的第oldbegin开始,长度为length的子数组复制到newarr的从newbegin开始的位置处。

比如oldarr={1,2,3}. newarr={5,6,7},oldbegin=1,newbegin=1,length=2.则执行后,结果为newarr为{5,2,3}.

比如oldarr={1,2,3,4}. newarr={5,6,7},oldbegin=1,newbegin=1,length=3.则执行后,结果为ArrayOutofBoundsException,因为newarr长度不够

public ArrayList(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}


//默认开始分配的大小10
public ArrayList() {
this(10);
}


//如果当前capacity<minCapacity,则将数组的capacity增长到minCapacity

public void ensureCapacity(int minCapacity) {
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3) / 2 + 1;	//newlength = (oldlength*3)/2+1
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);	//此语句是自增长数组的核心语句
}
}


添加元素

public boolean add(E e) {
ensureCapacity(size + 1); //将size+1,如果capacity不够,则重新分配
elementData[size++] = e;
return true;
}


添加多个元素

public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;	//新插入的元素大小
ensureCapacity(size + numNew); //插入元素钱首先判断容量够不够
System.arraycopy(a, 0, elementData, size, numNew);	//将a[0,...a,length-1] 放到 elementData[size,....size+numNew-1]中去
size += numNew;
return numNew != 0;
}


移除元素

public E remove(int index) {
RangeCheck(index);	//看index是否在数组的界里
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index,numMoved);
elementData[--size] = null; //使得垃圾回收器将其回收
return oldValue;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: