ArrayList,
ArrayList,
ArrayList 源码分析
构造函数
/**
* The minimum amount by which the capacity of an ArrayList will increase.
* This tuning parameter controls a time-space tradeoff. This value (12)
* gives empirically good results and is arguably consistent with the
* RI's specified default initial capacity of 10: instead of 10, we start
* with 0 (sans allocation) and jump to 12.
*/
private static final int MIN_CAPACITY_INCREMENT = 12;
/**
* The number of elements in this list.
*/
int size;
/**
* The elements in this list, followed by nulls.
*/
transient Object[] array;
上面是在ArrayList类内部的重要的(仅有的)变量,根据API我们可以知道:MIN_CAPACITY_INCREMENT是指扩容时每次增加的容量,默认为12,在前几个版本的ArrayList中默认的无参数的构造函数是直接赋予了默认大小的,默认大小为10,但是在现在的版本中这种方式已经被废弃了。size是指list中元素的个数,array是指存储所有元素的数组。
接下来看下构造函数:
public ArrayList(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException("capacity < 0: " + capacity);
}
array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);
}
public ArrayList() {
array = EmptyArray.OBJECT;
}
public ArrayList(Collection<? extends E> collection) {
if (collection == null) {
throw new NullPointerException("collection == null");
}
Object[] a = collection.toArray();
if (a.getClass() != Object[].class) {
Object[] newArray = new Object[a.length];
System.arraycopy(a, 0, newArray, 0, a.length);
a = newArray;
}
array = a;
size = a.length;
}
当构造参数为空或为0时,将EmptyArray.OBJECT赋予array,参数不为空时,参数小于0抛出异常,大于0时新建一个相同大小的Object数组。使用继承了Collection接口的子类对Array初始化时,使用collection的toArray方法将array数组赋值.
常用方法
add
/**
* Adds the specified object at the end of this {@code ArrayList}.
*
* @param object
* the object to add.
* @return always true
*/
@Override public boolean add(E object) {
Object[] a = array;
int s = size;
if (s == a.length) {
Object[] newArray = new Object[s +
(s < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : s >> 1)];
System.arraycopy(a, 0, newArray, 0, s);
array = a = newArray;
}
a[s] = object;
size = s + 1;
modCount++;
return true;
}
在末尾插入指定对象:如果超过array数组容量,则进行扩容,如果原数组size小于6,新建数组size大小为 原size + 12,否则新建数组size为1.5倍的原size,然后将原数组内东西拷贝到新建数组中,并将新建数组赋值给array。如果array数量未超过数组容量,则直接将新增对象塞到数组尾部。 返回true。
/**
* Inserts the specified object into this {@code ArrayList} at the specified
* location. The object is inserted before any previous element at the
* specified location. If the location is equal to the size of this
* {@code ArrayList}, the object is added at the end.
*
* @param index
* the index at which to insert the object.
* @param object
* the object to add.
* @throws IndexOutOfBoundsException
* when {@code location < 0 || location > size()}
*/
@Override public void add(int index, E object) {
Object[] a = array;
int s = size;
if (index > s || index < 0) {
throwIndexOutOfBoundsException(index, s);
}
if (s < a.length) {
System.arraycopy(a, index, a, index + 1, s - index);
} else {
// assert s == a.length;
Object[] newArray = new Object[newCapacity(s)];
System.arraycopy(a, 0, newArray, 0, index);
System.arraycopy(a, index, newArray, index + 1, s - index);
array = a = newArray;
}
a[index] = object;
size = s + 1;
modCount++;
}
private static int newCapacity(int currentCapacity) {
int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?
MIN_CAPACITY_INCREMENT : currentCapacity >> 1);
return currentCapacity + increment;
}
与上一方法类似,这个add方法参数有两个,插入的对象和指定的位置,实现的操作是将指定对象插入到Arraylist指定位置,注释中说明此方法在位置小于0或位置大于list的size时抛出越界异常。新建合适大小的数组,为了防止造成空间浪费,我们使用扩容的策略新建数组(上面已经介绍过),通过System.arraycpy方法将原数组进行分割粘贴处理然后给新数组赋值。然后将新数组赋值给array,最后将插入位置赋值。
get
@SuppressWarnings("unchecked") @Override public E get(int index) {
if (index >= size) { throwIndexOutOfBoundsException(index, size);
}
return (E) array[index];
}
如果传入的数值大于array的长度,抛出越界错误,否则返回数组array中指定位置的对象。
set
@Override public E set(int index, E object) {
Object[] a = array;
if (index >= size) {
throwIndexOutOfBoundsException(index, size);
}
@SuppressWarnings("unchecked") E result = (E) a[index];
a[index] = object;
return result;
}
将ArrayList某位置的元素进行设置,先进行判断,如果无越界则修改array数组的对应位置。
remove
@Override public E remove(int index) {
Object[] a = array;
int s = size;
if (index >= s) {
throwIndexOutOfBoundsException(index, s);
}
@SuppressWarnings("unchecked") E result = (E) a[index];
System.arraycopy(a, index + 1, a, index, --s - index);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return result;
}
指定位置删除:删除也是先进行越界判断,如果没有异常就通过Sysytem.arrarycopy进行处理。
@Override public boolean remove(Object object) {
Object[] a = array;
int s = size;
if (object != null) {
for (int i = 0; i < s; i++) {
if (object.equals(a[i])) {
System.arraycopy(a, i + 1, a, i, --s - i);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return true;
}
}
} else {
for (int i = 0; i < s; i++) {
if (a[i] == null) {
System.arraycopy(a, i + 1, a, i, --s - i);
a[s] = null; // Prevent memory leak
size = s;
modCount++;
return true;
}
}
}
return false;
}
指定对象删除:遍历array数组,寻找是否有与制定对象equal的对象,如果有就将array内,从指定对象的下一个位置开始的所有对象依次向前移动一位,覆盖掉要删除的对象,然后将array最后一个位置置空删除。参数可以是null。
相关文章
- 暂无相关文章
用户点评