ArrayList的介绍
1 ArrayList简介
ArrayList是List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的。),此类是线程不安全的。
2 ArrayList的构造函数
public ArrayList() //默认构造函数
public ArrayList(int initialCapacity) //生成一个指定容量的空列表
public ArrayList(Collection extends E> c) //生成一个包含指定元素的列表
3 ArrayList的Api
void trimToSize //把列表的容量修剪成列表的实际容量,删除动态增长的多余容量。
void ensureCapacity(int minCapacity) //根据传入的值对数组进行扩容,在数量已知的情况下
void ensureCapacityInternal(int minCapacity) //私有方法,根据传入的值对数组进行扩容
void ensureExplicitCapacity(int minCapacity) //传入数组进行扩容
void grow(int minCapacity) //进行扩容
int hugeCapacity(int minCapacity) //根据传入的值判断当前大小是否超过数组最大的大MAX_ARRAY_SIZE= Integer.MAX_VALUE - 8
int size() //获取列表大小
boolean isEmpty() //判断对象是否为空
boolean contains(Object o) //判断是否包含某个对象
int indexOf(Object o) //根据对象查询第一个索引下标
int lastIndexOf(Object o) //根据对象查询最后一个索引下标
Object clone() //对象进行复制
Object[] toArray() //将列表对象转成Object数组
T[] toArray(T[] a) //将列表对象转成某个固定对象的数组
E elementData(int index) //通过下标访问对象,内部方法
E get(int index) //通过下标访问对象
E set(int index, E element) //替换某个下标位置上的对象
boolean add(E e) //添加对象
void add(int index, E element) //在某个位置上添加对象,如果当前位置有相应的对象,则位置往右递增
E remove(int index) //删除某个对象通过下标
boolean remove(Object o) //通过对象查找删除某个对象 通过equals判断
void fastRemove(int index) //通过对象删除时的删除方法
void clear() //数据清空
boolean addAll(Collection extends E> c) //添加一个Collection队列到当前列表中
boolean addAll(int index, Collection extends E> c) //从某个位置开始添加一个Collection队列到当前列中
void removeRange(int fromIndex, int toIndex) //删除某个区间的数据
void rangeCheck(int index) //验证当前下标是否在实际数据范围内
void rangeCheckForAdd(int index) //添加数据到某个下标时 判断是否超过范围
String outOfBoundsMsg(int index) //数组越界显示字段
boolean removeAll(Collection> c) //删除传入的列表对象
boolean retainAll(Collection> c) //获取两个元素的交集 并把数据存入前面的列表中 l1.retainAll(l2)
boolean batchRemove(Collection> c, boolean complement) 私有方法 //retainAll调用的内部方法
void writeObject(java.io.ObjectOutputStream s) //
void readObject(java.io.ObjectInputStream s) //和WriteObject重写序列化方法
ListIterator listIterator(int index) //返回一个ListIterator从下标位置开始
ListIterator listIterator() //返回一个ListIterator接口的实现对象,下标从0开始
Iterator iterator() //返回Iterator接口具体实现对象
List subList(int fromIndex, int toIndex) //返回开始和结束下标中的对象
void subListRangeCheck(int fromIndex, int toIndex, int size) //判断取区间对象是是否
void forEach(Consumer super E> action) //输出对象
Spliterator spliterator() //生成一个Spliterator对象,用于遍历和分割队列 一般配合Collection的stream方法使用,1.8新增方法
boolean removeIf(Predicate super E> filter) //移除满足条件的所有元素
void sort(Comparator super E> c) //列表进行排序
ArrayList的数据结构
ArrayList里面的重要字段说明
elementData:Object类型的数组,存放ArrayList添加进来的元素,是一个动态数组,大小会根据ArrayList的容量的增长而增长。
size:ArrayList中实际数据的大小。
modCount:实现fail-fast机制,不同线程对同一个集合进行操作是的错误机制
ArrayList的重要方法源码解析
//数据的添加
public boolean add(E e) { //添加一个数据元素
ensureCapacityInternal(size + 1); // Increments modCount!! //确定ArrayList的大小
elementData[size++] = e; //添加e元素到ArrayList中 并ArrayList大小加1
return true;
}
public void add(int index, E element) { //添加一个元素到指定位置
rangeCheckForAdd(index); //判断当前位置是否越界(超出当前ArrayList大小和小于0)
ensureCapacityInternal(size + 1); // Increments modCount!! //确定ArrayList的大小
System.arraycopy(elementData, index, elementData, index + 1,
size - index); //把新元素存放位置后面的元素往后移动一位
elementData[index] = element; //把新元素放到指定位置
size++; //ArrayList大小加1
}
public boolean addAll(Collection extends E> c) { //往ArrayList中添加一个Collection集合
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount //把传入集合转为数组对象,通过长度确定ArrayList大小
System.arraycopy(a, 0, elementData, size, numNew); //把转为数组对象的Collection集合添加到ArrayList中
size += numNew;
return numNew != 0;
}
public boolean addAll(int index, Collection extends E> c) { //添加一个Collection集合到ArrayList中的指定位置
rangeCheckForAdd(index);
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityInternal(size + numNew); // Increments modCount 把传入集合转为数组对象,通过长度确定ArrayList大小
int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved); //计算指定位置插入数据是原数据往后移动位置,并移动
System.arraycopy(a, 0, elementData, index, numNew); //把转为数组对象的Collection集合添加到ArrayList中
size += numNew; //确定size
return numNew != 0;
}
private void ensureCapacityInternal(int minCapacity) { //确定ArrayList的大小
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { //判断是否为默认创建的空元素
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //大小为默认大小和传进来大小去最大值
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) { //判断并确定ArrayList大小
modCount++; //证明进行了ArrayList的数据添加操作
// 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); //自增的大小默认为原大小的1.5倍
if (newCapacity - minCapacity < 0) //如果自增大小小于添加数据后的带下,新的自增大小更改为传入数据大小
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0) //如果自增大小大于ArrayList中自定义最大大小,就把大小设置为int值得最大大小范围
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity); //数组进行自增
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
//ArrayList数据删除
public boolean remove(Object o) { //通过对象删除对象 通过循环ArrayList中的元素查找到需要删除的对象进行删除
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++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) { //快速删除对象 不需要对位置进行判断
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
protected void removeRange(int fromIndex, int toIndex) { //删除一个范围内的数据
modCount++;
int numMoved = size - toIndex; //通过删除最后的下标往前移动 然后把取消的数据设为null值
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);
// clear to let GC do its work
int newSize = size - (toIndex-fromIndex);
for (int i = newSize; i < size; i++) {
elementData[i] = null;
}
size = newSize;
}
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);
elementData[--size] = null; // clear to let GC do its work //最后一个元素设为null值
return oldValue;
}
public boolean removeAll(Collection> c) { //删除ArrayList中存在的输入的集合的元素
Objects.requireNonNull(c); //判断是否为空
return batchRemove(c, false);
}
private boolean batchRemove(Collection> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement) //complement:true 返回相同的元素 false 返回不同元素
elementData[w++] = elementData[r];
} finally {
if (r != size) { //如果不等于证明前面报了异常,把后面的部分补全
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
if (w != size) { //如果w!=size说明进行了删除操作,故需将删除的值赋为null
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
public E get(int index) { //通过下标返回数据 先判断下标是否正确
rangeCheck(index);
return elementData(index);
}
ArrayList的遍历方式
1、通过迭代器的方式去实现,既Iterator的方式
Iterator iterator = list.iterator;
while(iterator.hasNext()){
String value = iterator.next();
}
2、通过索引随机访问,ArrayList默认实现了RandomAccess
for(int i = 0;i
3、通过ForEach循环遍历
for(String str:list){
String value = str;
}
通过对比三种方式中随机访问的效率,迭代器的方式效率最低