ArrayList就是动态数组,,相当于Array的复杂版本,它提供了动态的增加和减少元素,实现了Collection和List接口,可以灵活的设置数组的大小。要注意的是ArrayList并不是线程安全的,因此一般建议在单线程中使用ArrayList。ArrayList的元素可以为null;
ArrayList底层使用数组存储元素,默认数组大小为10
//默认数组大小
private static final int DEFAULT_CAPACITY = 10;
//定义存储数组
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
1. indexOf(Object o)方法
//查找某个元素,返回找到的第一个的下标
public int indexOf(Object o) {
//如果查找null,返回元素为null的下标
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;
}
//查询不到返回-1
return -1;
}
2. lastIndexOf(Object o)方法
//查找元素,返回找到的最后一个元素的下标,方法同indexOf相似
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
//倒叙遍历数组,indexOf为正序
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
3. get(int index)方法
//根据下标获取数组元素
public E get(int index) {
//检查索引是否越界
rangeCheck(index);
//返回下标所在的元素
return elementData(index);
}
private void rangeCheck(int index) {
//如果索引大于数组长度,抛出索引越界异常
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
4. add(E e)方法:当数组容量不够时,扩容为原来的1.5倍
//添加元素
public boolean add(E e) {
//在加入元素前,检查数组容量是否足够
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
//判断现在的ArrayList是不是空的,如果是空的,minCapacity就取默认的容量和传入的参数minCapacity中的大值
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//判断是否需要扩容
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 添加一个元素后的长度大于数组长度时,进行扩容(只有在数组为空的时候,minCapacity为默认容量和传入参数的最大值,其余时候为当前数组元素个数+1)
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
//原数组长度
int oldCapacity = elementData.length;
//扩容后的容量为原容量+原容量/2
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// 数组复制
elementData = Arrays.copyOf(elementData, newCapacity);
}
4. set(int index, E element)方法 :替换掉原位置的元素
public E set(int index, E element) {
//检查index是否超出数组索引范围
rangeCheck(index);
E oldValue = elementData(index);
// 替换掉原位置的元素
elementData[index] = element;
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
5. add(int index, E element)方法 :插入元素,后边的元素后移
public void add(int index, E element) {
//检查索引是否越界,同上
rangeCheckForAdd(index);
//检查数组容量是否足够
ensureCapacityInternal(size + 1);
//进行数组插入位置后的元素复制,后移一位
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
//插入元素
elementData[index] = element;
size++;
}
6. remove(int index)方法
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
elementData[--size] = null;
return oldValue;
}