ArrayList
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。
构造方法:
ArrayList() :构造一个初始容量为 10 的空列表。
ArrayList(Collection<? extends E> c) : 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
ArrayList(int initialCapacity) : 构造一个具有指定初始容量的空列表。
方法摘要(部分)
boolean add(E e) 将指定的元素添加到此列表的尾部。
void add(int index, E element) 将指定的元素插入此列表中的指定位置。
boolean addAll(Collection<? extends E> c) 按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
boolean addAll(int index, Collection<? extends E> c) 从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
void clear() 移除此列表中的所有元素。
boolean contains(Object o) 如果此列表中包含指定的元素,则返回 true。
E get(int index) 返回此列表中指定位置上的元素。
int indexOf(Object o) 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
boolean isEmpty() 如果此列表中没有元素,则返回 true
int lastIndexOf(Object o) 返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
E remove(int index) 移除此列表中指定位置上的元素。
boolean remove(Object o) 移除此列表中首次出现的指定元素(如果存在)。
E set(int index, E element) 用指定的元素替代此列表中指定位置上的元素。
int size() 返回此列表中的元素数。
Object[] toArray() 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
T[] toArray(T[] a) 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
手动实现:
import java.util.Arrays;
import java.util.Collection;
public class ArrayList<E> {
private static final int DEFAULT_CAPACITY = 10;// 初始容量
transient Object[] elementData;// 存储元素的数组
private int size;// 数组大小
private static final Object[] EMPTY_ELEMENTDATA = {};// 空数组
public ArrayList() {// 无参构造方法
elementData = new Object[DEFAULT_CAPACITY];// 默认创建一个大小为10的数组
}
public ArrayList(int size) {// int型 有参构造方法
if (size < 0)
throw new IllegalArgumentException("默认的大小" + size);
else if (size == 0)// 大小为0,数组为空
elementData = EMPTY_ELEMENTDATA;
else
elementData = new Object[size];// 创建大小为size的数组
}
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();// 返回包含此 collection 中所有元素的数组
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)// 返回此 Object 的运行时类
// 复制指定的数组,截取或用 null 填充(如有必要),以使副本具有指定的长度。
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
elementData = EMPTY_ELEMENTDATA;
}
}
private void IsCapacityEnough(int nowsize) {// 判断是否需要扩容
if (nowsize > DEFAULT_CAPACITY)
explicitCapacity(nowsize);// 判断是否大于默认大小
}
private void explicitCapacity(int nowsize) {
if (nowsize > elementData.length)
grow(nowsize);// 如果添加元素后大小超出现有大小,则进行扩容
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;// 定义一个数组最大的容量的常量为最大值
private void grow(int nowsize) {// 数组扩容
int oldCapacity = elementData.length;// 数组长度
int newCapacity = oldCapacity + (oldCapacity >> 1);// 扩容增加原大小的0.5倍
if (newCapacity - nowsize < 0)
newCapacity = nowsize;// 增容后空间仍不够,将增加元素后的大小作为扩容后大小
if (newCapacity - MAX_ARRAY_SIZE > 0)// 若扩容后大小超过数组最大的容量
// 判断要需要的扩容空间是否大于数组最大长度,如果大于则容量为 MAX_VALUE ,否则为 MAX_ARRAY_SIZE
newCapacity = nowsize > MAX_ARRAY_SIZE ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
elementData = Arrays.copyOf(elementData, newCapacity);// 扩容后的数组
}
public boolean add(E e) {
IsCapacityEnough(size + 1); // 判断是否需要扩容
elementData[size++] = e;
return true;
}
private void checkRangeForAdd(int index) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException("指定的index超过界限");
}
}
public void add(int index, E e) {
checkRangeForAdd(index);// 判断是否越界
IsCapacityEnough(size + 1);
// 将index的元素及以后的元素向后移一位
System.arraycopy(elementData, index, elementData, index + 1, size - index);
// 将index下标的值设为e
elementData[index] = e;
size++;
}
public boolean addAll(Collection<? extends E> c) {// 将该 collection 中的所有元素添加到此列表的尾部
Object[] a = c.toArray();
int numNew = a.length;// 集合长度
IsCapacityEnough(size + numNew); // 判断是否需要扩容
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}
public boolean addAll(int index, Collection<? extends E> c) {
checkRangeForAdd(index);// 下标是否越界
Object[] a = c.toArray();
int numNew = a.length;
IsCapacityEnough(size + numNew); // 是否扩容
int numMoved = size - index;
if (numMoved > 0)// 从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
System.arraycopy(elementData, index, elementData, index + numNew, numMoved);
System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}
public void clear() {// 移除此列表中的所有元素
for (int i = 0; i < size; i++)// 将数组的值设置为空
elementData[i] = null;
size = 0;// 设置数组大小为0
}
public int indexOf(Object o) {// 返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i] == null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
public int lastIndexOf(Object o) {// 返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1
if (o == null) {
for (int i = size - 1; i >= 0; i--)
if (elementData[i] == null)
return i;
} else {
for (int i = size - 1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
public boolean contains(Object o) {// 如果此列表中包含指定的元素,则返回 true
return indexOf(o) >= 0;// 查找首次出现的指定元素的索引
}
public E get(int index) {// 返回此列表中指定位置上的元素
checkRangeForAdd(index);// 是否越界
return (E) elementData[index];
}
public boolean isEmpty() {// 判断集合是否为空
return size == 0;// 通过数组大小
}
public E remove(int index) {// 移除此列表中指定位置上的元素
checkRangeForAdd(index);// 是否越界
E oldValue = (E) elementData[index];
int numMoved = size - index - 1;// 需前移的元素的个数
if (numMoved > 0)
System.arraycopy(elementData, index + 1, elementData, index, numMoved);// 将index后面的元素向前移一位
elementData[--size] = null;// 缩减size大小,并将原最后一位置空
return oldValue;
}
public boolean remove(Object o) {// 移除此列表中首次出现的指定元素
if (contains(o)) {// 如果包含指定元素
remove(indexOf(o));// 移除首次出现的指定元素
return true;
} else {
return false;
}
}
public E set(int index, E element) {// 用指定的元素替代此列表中指定位置上的元素
checkRangeForAdd(index);// 是否越界
E oldValue = (E) elementData[index];// 记录指定位置上的元素
elementData[index] = element;// 赋值
return oldValue;
}
public int size() {// 返回此列表中的元素数
return size;
}
public Object[] toArray() {// 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
return Arrays.copyOf(elementData, size);
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {// 按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)// 如果数组大小大于集合大小,则不可能包含所有
a[size] = null;
return a;
}
}
总结:以上仅供参考,ArrayList的底层是可变数组,有下标,添加顺序和输出顺序一致。