成员变量和常量
//存储数据的数组
transient Object[] elementData;
//数据的个数
private int size;
//默认的容量
private static final int DEFAULT_CAPACITY = 10;
//空数组
private static final Object[] EMPTY_ELEMENTDATA = {};
//空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//容器被修改的次数, 数组中数据的添加,删除 会修改该参数
protected transient int modCount = 0;
//最大容量判定值
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
构造方法
//指定容量的构造函数
public ArrayList(int initialCapacity) {
//elementData初始化为指定大小的数组
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() {
//先给一个空数组
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
//将另一个容器的数组复制到当前数组
public ArrayList(Collection<? extends E> c) {
//获取入参集合的数组数据。赋值给elementData
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}
//入参的集合为空,直接将elementData赋值为空数组
else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
添加数据相关的方法
//顺序添加数据
public boolean add(E e) {
//检查容量是否足够,不够,则要申请一个更大的数组,并复制原数组的数据到新数组, 入参为当前容器数据个数+1
ensureCapacityInternal(size + 1); // Increments modCount!!
//赋值,并且更新size
elementData[size++] = e;
return true;
}
//向指定位置添加数据
public void add(int index, E element) {
//检查index的合法性,index不能为负数,不能大于size,否则抛异常
rangeCheckForAdd(index);
//检查容量是否足够,不够,则要申请一个更大的数组,并复制原数组的数据到新数组,
ensureCapacityInternal(size + 1); // Increments modCount!!
//将数组index位置开始的数据,全部复制到index+1开始之后的位置,(通俗点说,index位置及之后的数据全部向后顺移一个位置)
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//直接给index位置赋值
elementData[index] = element;
//size 加一
size++;
}
public boolean addAll(Collection<? extends E> c) {
//获取集合的数组数据
Object[] a = c.toArray();
//获取数据的长度
int numNew = a.length;
//检查容量是否足够,不够,则要申请一个更大的数组,并复制原数组的数据到新数组,
ensureCapacityInternal(size + numNew); // Increments modCount
//将a的数据复制到 elementData 的 size开始以及之后的位置
System.arraycopy(a, 0, elementData, size, numNew);
//size需要加上添加的数据的个数
size += numNew;
//返回值为 添加进来的数据个数是否为0
return numNew != 0;
}
public boolean addAll(int index, Collection<? extends E> c) {
//检查添加的位置是否合法
rangeCheckForAdd(index);
//获取集合的数组数据
Object[] a = c.toArray();
//获取数据的长度
int numNew = a.length;
//检查容量是否足够,不够,则要申请一个更大的数组,并复制原数组的数据到新数组,
ensureCapacityInternal(size + numNew); // Increments modCount
//原数组要移动的数据的个数
int numMoved = size - index;
//大于0 说明添加的index的位置有数据,需要后移index及以后的数据 , 使得空出来的位置可以放入添加进来的数据
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);
//将添加进来的数据复制到放入到elementData中
System.arraycopy(a, 0, elementData, index, numNew);
//size需要加上添加的数据的个数
size += numNew;
//返回值为 添加进来的数据个数是否为0
return numNew != 0;
}
//ArrayList的toArray方法
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
ensureCapacityInternal方法
//入参为需求的容量大小
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
//如果elementData为空数组
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
//返回DEFAULT_CAPACITY(10) 和 需求的容量大小 的 更大的值
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
//如果不是空数组,直接返回需求的容量大小
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
//modCount加一
modCount++;
// overflow-conscious code
//如果当前需求的容量大小 大于 当前数组的大小。则要申请一个更大的数组来存放数据
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
//获取原数组容量大小
int oldCapacity = elementData.length;
//新数组容量大小为 (原数组容量大小 加上 原数组容量的一半)
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果新数组的容量大小 小于 需求的容量大小
if (newCapacity - minCapacity < 0)
//则新的数组的容量大小为需求的容量大小
newCapacity = minCapacity;
//新容量超过了MAX_ARRAY_SIZE
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//将原数组cpoy给新数组,并将新数组赋值给elementData
elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
//需求的容量已经溢出int能表示的最大值,直接抛异常
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
//需求的容量大于MAX_ARRAY_SIZE , 则返回 Integer.MAX_VALUE
//否则返回MAX_ARRAY_SIZE
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
rangeCheckForAdd方法
private void rangeCheckForAdd(int index) {
//index 不能大于size ,不允许添加的数据的数组前面有空位置
if (index > size || index < 0)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
get方法
public E get(int index) {
//检查index是否合法
rangeCheck(index);
//返回数组对应下标的数据
return elementData(index);
}
//Object数组要进行强转
E elementData(int index) {
return (E) elementData[index];
}
set方法
public E set(int index, E element) {
//检查index是否合法
rangeCheck(index);
//获取数组指定下标的数据
E oldValue = elementData(index);
//将数组指定下标的数据设置为入参的element
elementData[index] = element;
//返回原本的值
return oldValue;
}
remove方法
//按下标移除数据
public E remove(int index) {
//检查index合法性
rangeCheck(index);
//modCount加一
modCount++;
//获取原本下标位置的值
E oldValue = elementData(index);
//需要将后面位置的数据复制到前面来补充该位置
//计算需要复制的数据的个数
int numMoved = size - index - 1;
//被移除的数据不是size-1位置的数据,则numMoved大于0
if (numMoved > 0)
//将index+1及以后位置的数据 复制到 index及以后位置上。
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//上面复制完成后,size位置的数据已经在size-1的位置存在了,移除掉size位置的数据
//或者如果本来移除的就是最后一个数据,直接置空
elementData[--size] = null; // clear to let GC do its work
//返回被移除的值
return oldValue;
}
//按 数据的equals方法 移除数据
public boolean remove(Object o) {
//如果入参值为null
if (o == null) {
//遍历数组
for (int index = 0; index < size; index++)
//如果该值为null
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;
}
}
return false;
//显然这里找到一个符合条件的数据删除后,就返回了,如果还有符合条件的数据并不会接着移除
}
private void fastRemove(int index) {
//modCount增加
modCount++;
//计算需要复制的数据的个数
int numMoved = size - index - 1;
//被移除的数据不是size-1位置的数据,则numMoved大于0
//将index+1及以后位置的数据 复制到index及以后位置上。
if (numMoved > 0)
//将index+1及以后位置的数据 复制到 index及以后位置上。
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
//返回被移除的值
elementData[--size] = null; // clear to let GC do its work
}
clear方法
public void clear() {
//modCount加1
modCount++;
//将数组中的数据全部置为null
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
//size置为0
size = 0;
}
查找数据在数组位置
//从头往后找,找到就返回对应的下标
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
}
//找的不是null值,使用equals来比较数据
else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
//从后往前找,找到就返回对应的下标
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
}
//找的不是null值,使用equals来比较数据
else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
Iterator的相关方法
public Iterator<E> iterator() {
//实例化Itr对象
return new Itr();
}
private class Itr implements Iterator<E> {
//下一个返回的数据的下标
int cursor; // index of next element to return
//当前遍历出来的数据的下标
int lastRet = -1; // index of last element returned; -1 if no such
//初始expectedModCount为modCount
int expectedModCount = modCount;
Itr() {}
//cursor不等于size,则还有数据可以遍历
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
//获取数据
public E next() {
//检查expectedModCount 和 modCount是否相等,不等则抛出异常(其他线程修改了当前集合的数据,则本次遍历是无效的)
checkForComodification();
//将cursor赋值给i
int i = cursor;
//超过了size , 抛出异常
if (i >= size)
throw new NoSuchElementException();
//获取数组的数据
Object[] elementData = ArrayList.this.elementData;
//超过数组长度,抛出异常
if (i >= elementData.length)
throw new ConcurrentModificationException();
//将cursor 加一 ,为下一个要获取的数据的下标
cursor = i + 1;
//将i赋值给lastRet
//返回lastRet 位置的数据
return (E) elementData[lastRet = i];
}
//移除数据
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
//检查expectedModCount 和 modCount是否相等,不等则抛出异常(其他线程修改了当前集合的数据,则本次遍历时无效的)
checkForComodification();
try {
//调用外部类ArrayList的remove方法,移除数组中该下标的数据
ArrayList.this.remove(lastRet);
//修改cursor 为lastRet , lastRet位置的数据被移除,则后面的数据全部被向前复制了一遍 ,则 lastRet为下一次遍历获取的数据的下标
cursor = lastRet;
//lastRet 修改为 -1
lastRet = -1;
//调用remove方法,改变了modCount
//修改expectedModCount 为 modCount
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
}
final void checkForComodification() {
//Itr 实例化时的expectedModCount 不等于modCount ,则抛异常
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
subList方法,所有对数据的操作的方法就不一一看了,很简单了,都是使用parent 或者 ArrayList.this.elementData (原本的数组)去操作的。
public List<E> subList(int fromIndex, int toIndex) {
//检查截取下标的合法性
subListRangeCheck(fromIndex, toIndex, size);
//返回SubList对象,持有了this(ArrayList对象)
return new SubList(this, 0, fromIndex, toIndex);
}
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
SubList(AbstractList<E> parent,
int offset, int fromIndex, int toIndex) {
//parent为实例化传入进来的原本的ArrayList对象
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}
ArrayList还是比较简单的,可以作为学习源码的入门类。
本文详细解析了ArrayList类的成员变量、构造方法和关键方法,如添加、移除、扩容等,助你理解容器数据结构实现原理。
1044

被折叠的 条评论
为什么被折叠?



