java集合源码阅读(一) ArrayList
2019-03-21 本文已影响0人
坠叶飘香
1. ArrayList的继承关系
ArrayList.png2.重要属性
(1)size:实际元素个数
因为size这个值是时时更新的,通过size() 获取元素个数时,不耗时。
private int size;
public int size() {
return size;
}
(2)elementData:数据容器
从这里可以看出,ArrayList的数据实际上是存放在一个数组中,所以ArrayList可以快速的获取处于index位的元素
transient Object[] elementData;
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
3.add方法
数组elementData容器的默认大小0,第一次add数据时,会创建一个length为10的elementData;以后的每次add动作一旦发现elementData的length不够放入新的元素,会再次创建一个新的elementData,
新elementData的length=oldlength +oldlength/2
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
4.remove方法
(1) 通过index删除相应位置的元素:直接执行System.arraycopy
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);
}
//这里不忘把最后一个元素设置为null,让GC可以将它回收
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
(2) 通过value移除
- 循环遍历数组,判断每个元素是否与value相等,如果找到一个相等的,执行System.arraycopy
- 如果存在多个相同的value,只会移除第一个
- ArrayList元素可以添加null元素
- null元素与非null需要分开处理
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;
}
5.set方法:直接修改数组位于index处的元素
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
6.关于使用ListIterator还是for遍历的问题
两种遍历的不同点主要在获取index处的元素
从代码上看ListIterator比for多了两次i的检测和一次cursor的求值;在数据量很小的情况下没有什么差别,
用5000个数据来遍历的话,for的时间为1,ListIterator为2。
ListIterator:
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
for:
public E get(int index) {
rangeCheck(index);
return elementData(index);
}