持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情
ArrayList底层是数组( Object类型)默认容量10,直接get下标index,时间复杂度O(1)
源码分析:
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// 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);
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);
}
缩容:
先copy一个目标数组,计算出删除下标后面有多少个元素,然后将后边的元素移动到被删除下标的位置,最后一个数组下标value等于null
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
}
modCount在扩容和添加的时候会modCount++,在遍历时判断是否相等,不允许在遍历时,对arrayList添加操作
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
final int expectedModCount = modCount;
@SuppressWarnings("unchecked")
final E[] elementData = (E[]) this.elementData;
final int size = this.size;
for (int i=0; modCount == expectedModCount && i < size; i++) {
action.accept(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
- ArrayList:线程不安全,扩容是原来的1.5倍,容量默认10
- Vector:线程安全 (add synchronize方法),扩容是原来的2倍,容量默认10,但是可以自定义扩容
LinkedList原理
底层基于双向链表结构
LinkedList记录头结点first方便遍历,利用尾结点last插入尾插法
采用折半查找(查询更长的元素),长度为100的话,除以2,等于50,判断元素在上还是下,可以再折半,再去判断大小,元素在哪一部分,时间复杂度O(logn)