java基础list集合分享

79 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

image.png 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
}

image.png

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原理

底层基于双向链表结构

image.png

LinkedList记录头结点first方便遍历,利用尾结点last插入尾插法

采用折半查找(查询更长的元素),长度为100的话,除以2,等于50,判断元素在上还是下,可以再折半,再去判断大小,元素在哪一部分,时间复杂度O(logn)