1. ArrayList 的实现
ArrayList 底层数据结构:数组
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
transient Object[] elementData; // 存储ArrayList元素的数组缓冲区
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 用于默认大小的空实例的共享空数组实例
private int size; // ArrayList的大小(包含的元素数)
private static final int DEFAULT_CAPACITY = 10; // 默认初始容量
protected transient int modCount = 0; // 此列表在结构上被<i>修改的次数</i>
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 要分配的数组的最大大小
ArrayList 扩容机制
1)代码分析
① add 方法
/**
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return <tt>true</tt> (as specified by {@link Collection#add})
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // 确认 List 容量,如果不够,容量加 1。注意:只加 1,保证资源不被浪费
elementData[size++] = e;
return true;
}
② ensureCapacityInternal 方法
private void ensureCapacityInternal(int minCapacity) {
// 判断 ArrayList 是否初始化
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
唯有调用 ArrayList 的无参构造方法才会满足
elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 这个条件。
有参构造方法可以在创建对象时为其进行一些初始化操作,如对类的字段进行赋值等。而无参构造则不需要进行任何初始化操作。
故调用 ArrayList 的无参构造方法等同于 ArrayList 未初始化,
elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 等同于判断 ArrayList 是否初始化
若 ArrayList 未初始化,则 minCapacity = 10
③ ensureExplicitCapacity 方法
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
比较 elementData.length(存储 ArrayList 元素的数组缓冲区长度 || 数组长度)与 minCapacity(最小容量 || 新增数据元素的数组下标 index )的大小,若大于,则插入新增元素;反之,则扩容
④ grow 方法 - 扩容
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
若 elementData.length * 1.5(1.5 * length)< minCapacity(index)则将 minCapacity 设置为数组的容量;反之则将 Integer.MAX_VALUE 设置为数组的容量
将旧数组中的数据拷贝到新数组中
插入新增元素
2)文字叙述
第一步,确认 List 容量,如果不够,容量加 1
第二步,判断 ArrayList 是否初始化,若否,设置最小容量为 10;
第三步,判断数组长度是否大于新增数据元素的数组下标,若是,则插入新增元素【流程结束】;反之,扩充
第四步,判断 1.5 倍数组长度是否小于新增数据元素的数组下标,若是,则将最小容量(size + 1)为数组的容量;反之,则将 Integer.MAX_VALUE 设置为数组的容量
第五步,将旧数组中的数据拷贝到新数组中
第六步,插入新增元素【流程结束】
2. LinkedList 的实现
LinkedList 底层数据结构:链表(双向链表)
3. ArrayList 和 LinkedList 的区别
ArrayList | LinkedList | |
底层数据结构 | 数组 | 链表(双向链表) |
查询操作 | √ | × |
增删操作 | × | √ |