构造方法:
这个类中有一个Object[]的对象来存储数据,代码是:
this.elementData = new Object[initialCapacity];//存储对象的数组
initialCapacity默认是10,这个elementData定义的时候用transient定义,不知道什么意思。size为集合的长度int。默认没有给值,所以是0。
构造方法:
public ArrayList(int initialCapacity) {
this.elementData = new Object[initialCapacity];
}
构造方法:
public ArrayList() {
this(10);
}
在构造方法中
public ArrayList(Collection<? extends E> c) {
//返回一个Object[]的副本对象(大部分是这样),长度会是内部变量的长度size,而不是这个Object[]的长度
elementData = c.toArray();
size = elementData.length;
//这里验证内部的值是否是Object[],然后依情况转成Object类型
if (elementData.getClass() != Object[].class)
//这里复制出来的Onject[]值所占空间为size,内部变量的数目也是size
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
在这个构造方法中会将c中的值转为Object[]类型,在c.toArray()中,一般会传出一个对象的副本,即利用copy传出elementData的数据。所以这里很有可能是复制了两次数据。
add方法
返回的是否添加成功。注意,这里面竟然可以添加null值。
public boolean add(E e) {
//增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
ensureCapacity(size + 1);
//复制后size+1
elementData[size++] = e;
return true;
}
类中的E泛型 不过都会当成Object处理??
上面的第一句代码:
public void ensureCapacity(int minCapacity) {
//不知道这句是干什么的?????????????????????
modCount++;
//获取当前数组长度,而并不是内部拥有的变量size
int oldCapacity = elementData.length;
//如果总空间不够的话
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
//开辟1.5倍+1的空间
int newCapacity = (oldCapacity * 3)/2 + 1;
//如果依然不够的话,直接开辟minCapacity的空间
if (newCapacity < minCapacity)
newCapacity = minCapacity;
//将数据复制到新的数组中
elementData = Arrays.copyOf(elementData, newCapacity);
}
}
add(int index, E element) 将指定的元素插入此列表中的指定位置。
public void add(int index, E element) {
//这个就不说了,越界
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
//容量保证
ensureCapacity(size+1);
//复制index后size-index长度的值到index+1的位置上,就是将index后面的内容向后移动一位,把index这个位置空出来
System.arraycopy(elementData, index, elementData, index + 1,size - index);
//赋值
elementData[index] = element;
//大小+1
size++;
}
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
//a.length 相当于复制过来c的size。这里也是数组所占空间
int numNew = a.length;
ensureCapacity(size + numNew);
//将加入的a复制到size之后,注意这里都是数组的位置,
System.arraycopy(a, 0, elementData, size, numNew);
//更新size
size += numNew;
//这个很有特色,按照添加的长度来判断是否成功。很危险
return numNew != 0;
}
public boolean addAll(int index, Collection<? extends E> c) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew);
int numMoved = size - index;
//这里是判断是否需要系统,如果index 和size一样大的话就复制移动了。
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
get方法
public E get(int index) {
//范围检查
RangeCheck(index);
//竟然会强转,不过想想也很正常。
return (E) elementData[index];
}
//只是做了一个越界检查
private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
}
size方法
public int size() {
//直接返回size的值。
return size;
}
clear方法
public void clear() {
//这里又不知道在干什么
modCount++;
//看来数组的空间不会改变,内部的变量都清空了。
for (int i = 0; i < size; i++)
//所有的值赋了空值。
elementData[i] = null;
size = 0;
}
remove方法
返回删除对象
public E remove(int index) {
//判断是否越界
RangeCheck(index);
//这里又不知道在干什么
modCount++;
//强转
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;
}
返回是否删除成功
public boolean remove(Object o) {
//第一步直接把对象强转为Object类型了。
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++)
//注意这里判断的删除只是equals相同就行,这个地方很有奇异,
if (o.equals(elementData[index])) {
fastRemove(index);
//只会删除碰到的第一条相同对象
return true;
}
}
//没找到会返回false。
return false;
}
快速删除
private void fastRemove(int index) {
//又是这个神秘的变量
modCount++;
//和上面的删除是一个人写的,一样。
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index, numMoved);
//size-1
elementData[--size] = null;
}
ArrayList里面的removeAll是调用的下面class的方法。
AbstractCollection.class
public boolean removeAll(Collection<?> c) {
boolean modified = false;
Iterator<?> e = iterator();
while (e.hasNext()) {
//包含的方法下面会看到。
if (c.contains(e.next())) {
e.remove();
//这里是删除所有的
modified = true;
}
}
return modified;
}
public boolean retainAll(Collection<?> c) {
boolean modified = false;
Iterator<E> e = iterator();
while (e.hasNext()) {
if (!c.contains(e.next())) {
// 不包含的关系,就是几乎会删除掉原对象中所有的值
e.remove();
modified = true;
}
}
return modified;
}
indexOf方法
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
//在size之前找到空,会返回,超过size后没用
if (elementData[i]==null)
return i;
} else {
//依然只是比较equals方法。
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
//只返回查找的第一个。
return i;
}
//找不到返回 int -1
return -1;
}
lastIndexOf方法
lastIndexOf(Object o)
返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
和index一样,只是这个循环从最后一个开始,向前循环。所以查找的是最后一个。
toArray方法
public Object[] toArray() {
//返回一个数组,数组空间和变量同样大小的。
return Arrays.copyOf(elementData, size);
}
未定义泛型的时候Object[] 不能强转成 E[] ,
trimToSize方法
将此 ArrayList 实例的容量调整为列表的当前大小
public void trimToSize() {
//未知
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
}
set方法
E set(int index,E element)
就是将对应未知的变量换成新的,将旧的值返回,当然先是对越界做过滤。
isEmpty方法
isEmpty()
public boolean isEmpty() {
return size == 0;
}
代码更容易懂。
contains方法
如果此列表中包含指定的元素,则返回 true。
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public boolean containsAll(Collection<?> c) {
Iterator<?> e = c.iterator();
while (e.hasNext())
if (!contains(e.next()))
return false;
return true;
}
这里是不讲究顺序,只要c中的变量都有就行。例如:a={1,3,2,4},b={1,3,3} 这里,a包含b。
clone方法
克隆被覆写
public Object clone() {
try {
ArrayList<E> v = (ArrayList<E>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
好了ArrayList 就算看完了。