ArrayList底层数据结构是数组,能够高效的在指定位置上进行查找、修改,但是对于插入操作效率不是很高。如果向列表末尾插入元素,当底层数组容量不足以容纳时,需要进行扩容操作。当在指定位置插入时,需要将指定位置以及之后的元素往后移动,腾出位置给新加入的元素。
底层数据结构:
private static final int DEFAULT_CAPACITY = 10; // 默认容量是10,在第一次添加元素时新建数组
/**
* DEFAULTCAPACITY_EMPTY_ELEMENTDATA和EMPTY_ELEMENTDATA区别:
* DEFAULT_CAPACITY:表明当前集合容量就是0
* DEFAULTCAPACITY_EMPTY_ELEMENTDATA:表明当前集合尚未添加元素,而容量为默认容量10,
* 数组新建发生在第一次加入元素时(加入第一个元素之前暂不新建数组)。
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData; // elementData中保存的就是集合中元素
private int size; // 当前集合中元素个数
构造方法:
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) { // 立刻新建数组
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) { // 指定容量为零,数组指定为:EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
public ArrayList() {
// 默认容量为10,而在添加第一个元素之前,
// 数组指定为:DEFAULTCAPACITY_EMPTY_ELEMENTDATA
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
// 根据另一个集合中的所有元素构建新List,元素都是相同的。
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
数组扩容:
private void ensureCapacityInternal(int minCapacity) {
// 说明是默认容量,尚未添加任何元素,令minCapacity
// 最小为DEFAULT_CAPACITY(10)
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++; // 集合结构变化次数,定义在父类AbstractList中
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// 扩容机制为:新建一个容量为当前数组容量 1.5 倍的新数组,
// 将当前数组中元素全部拷贝到新数组中
private void grow(int minCapacity) {
int oldCapacity = elementData.length; // 原数组最大容量
int newCapacity = oldCapacity + (oldCapacity >> 1); // 右移一位相当于除以2
if (newCapacity - minCapacity < 0) // 最小扩容到minCapacity
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity); // 数组元素拷贝
}
添加元素操作:
public E set(int index, E element) { // 替换集合某个位置上元素,返回旧元素
rangeCheck(index); // // 检查index值是否合法
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
public boolean add(E e) { // 向集合中添加元素(末尾)
ensureCapacityInternal(size + 1); // 如果当前数组容量不足,需要进行数组扩容
elementData[size++] = e;
return true;
}
/**
* 向指定位置插入元素,此位置以及之后元素顺次后移
* index的值在 0 和 size 值之间
*/
public void add(int index, E element) {
rangeCheckForAdd(index); // 检查index值是否合法
ensureCapacityInternal(size + 1); // 如果当前数组容量不足,需要进行数组扩容
System.arraycopy(elementData, index, elementData, index + 1,
size - index); // 此方法完成数组元素移动
elementData[index] = element; // 插入元素
size++;
}
集合操作(removeAll、retailAll):
/**
* 从当前集合中删除这样的元素:此元素存同时在集合c中,集合减操作
* 如:{1, 2, 3, 4} - {3, 4, 5} = {1, 2}
*/
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
/**
* 从当前集合删除这样的元素:此元素不存在集合c中,集合交操作
* 如:{1, 2, 3, 4} ∩ {3, 4, 5} = {3, 4}
*/
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
/**
* 集合批量删除算法
*/
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) // 包含或不包含
elementData[w++] = elementData[r]; // 符合条件元素向前移动,不符合的会被覆盖
} finally {
if (r != size) { // contains发生异常,某个元素不符合集合c类型
System.arraycopy(elementData, r,
elementData, w,
size - r); // 将集合中剩余未比较的元素以w为起始位置加入
w += size - r; // 更新w值
}
if (w != size) { // 说明存在元素被删除
for (int i = w; i < size; i++)
elementData[i] = null; // 数组剩余位置设为null
modCount += size - w;
size = w; // 更新集合size
modified = true;
}
}
return modified;
}
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
List<Integer> list2 = new ArrayList<>();
list2.add(1);
list2.add(2);
list2.add(3);
list2.add(4);
List<Integer> list3 = new ArrayList<>();
list3.add(3);
list3.add(4);
list3.add(5);
System.out.println(list1.removeAll(list3)); // true
System.out.println(list2.retainAll(list3)); // true
System.out.println(list1); // [1, 2]
System.out.println(list2); // [3, 4]
}
}
其他一些实用方法(replaceAll、sort、removeIf):
import java.util.ArrayList;
import java.util.List;
import java.util.function.UnaryOperator;
public class ArrayListDemo {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
// list1.replaceAll(integer -> integer * integer); // Lambda
list1.replaceAll(new UnaryOperator<Integer>() {
@Override
public Integer apply(Integer integer) {
return integer * integer;
}
});
System.out.println(list1); // [1, 4, 9]
}
}
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(2);
list.add(3);
list.add(1);
list.sort(Comparator.comparingInt(value -> value));
System.out.println(list); // [1, 2, 3]
list.sort(Comparator.comparingInt(value -> -value));
System.out.println(list); // [3, 2, 1]
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class ArrayListDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
// list.removeIf(integer -> integer % 2 == 0); // Lambda
list.removeIf(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer % 2 == 0;
}
});
System.out.println(list); // [1, 3]
}
}