ArrayList和LinkedList

158 阅读2分钟

ArrayList和LinkedList

ArrayList 是线性表(数组) get() 直接读取第几个下标,复杂度 O(1) add(E) 添加元素,直接在后面添加,复杂度O(1) add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n) remove()删除元素,后面的元素需要逐个移动,复杂度O(n)

LinkedList 是链表的操作 get() 获取第几个元素,依次遍历,复杂度O(n) add(E) 添加到末尾,复杂度O(1) add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n) remove()删除元素,直接指针指向操作,复杂度O(1)

ArrayList 初始容量被设置为10。当ArrayList中的元素超过10个以后,会重新分配内存空间,使数组的大小增长到15

arraylist 首次添加元素会分配默认10个内存空间,如果超过10个再次添加元素会通过位运算扩容

逻辑如下

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);
}

Arrays.copyOf源码

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}



public static void arraycopy(

                             Object src,  //源数组

                             int srcPos,  //源数组的起始位置

                             Object dest, //目标数组

                             int destPos, //目标数组的起始位置

                             int length   //复制长度

                             )

ArrayList和LinkedList区别以及时间复杂度与空间复杂度##

ArrayList 是线性表(数组) get() 直接读取第几个下标,复杂度 O(1) add(E) 添加元素,直接在后面添加,复杂度O(1) add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n)

public void add(int index, E element) {
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1);  // Increments modCount!!
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}

remove()删除元素,后面的元素需要逐个移动,复杂度O(n)

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

    return oldValue;
}

LinkedList 是链表的操作 get() 获取第几个元素,依次遍历,复杂度O(n),类似二分法查找,小于index,从前往后查,大于index,从后往前查

Node<E> node(int index) {
    // assert isElementIndex(index);

    if (index < (size >> 1)) {
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}

add(E) 添加到末尾,复杂度O(1) add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n)

remove()删除元素,直接指针指向操作,复杂度O(1),默认删头结点

E unlink(Node<E> x) {
    // assert x != null;
    final E element = x.item;
    final Node<E> next = x.next;
    final Node<E> prev = x.prev;

    if (prev == null) {
        first = next;
    } else {
        prev.next = next;
        x.prev = null;
    }

    if (next == null) {
        last = prev;
    } else {
        next.prev = prev;
        x.next = null;
    }

    x.item = null;
    size--;
    modCount++;
    return element;
}