ArrayList与LinkedList区别

ArrayList与LinkedList区别

ArrayList

从构造函数中,可以看出,ArrayList底层结构是一个对象数组

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        //对象数组
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
get方法
public E get(int index) {
    rangeCheck(index);
	//直接通过索引访问数组
    return elementData(index);
}
add方法

add有两种实现: add(E e),直接数组尾部插入即可, add(int index, E element),需要调整数组后,进行插入,直接介绍第二种方法,可以明显得发现ArrayListLinkedList的区别

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

ensureCapacityInternal方法,首先调用calculateCapacity方法,计算所需的数组容量,之后调用ensureExplicitCapacity,如果容量不够,则调用grow方法,进行扩容操作,每次扩容大小,为原来数组大小一半

private void ensureCapacityInternal(int minCapacity) {
	ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
    	return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

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

LinkedList

从源码中,可以直观看出,LinkedList底层是双向链表结构

/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;

/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
get方法

需要遍历链表,里面有个小技巧,如果index < size/2从头开始遍历,否则从链表尾部进行遍历

public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}

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方法

跟ArrayList一样提供两种add形式

add(E, e),直接在链表尾部直接插入。

public boolean add(E e) {
    linkLast(e);
    return true;
}

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

add(int index, E element),插入链表指定位置, 也是一个O(1)的操作

public void add(int index, E element) {
    checkPositionIndex(index);
    if (index == size)  linkLast(element);
    else linkBefore(element, node(index));
}

void linkBefore(E e, Node<E> succ) {
    // assert succ != null;
    final Node<E> pred = succ.prev;
    final Node<E> newNode = new Node<>(pred, e, succ);
    succ.prev = newNode;
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;
}

总结

ArrayList和LinkedList的区别有以下几点:

  • ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于双向链表的数据结构;
  • 对于随机访 问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针;
  • 对于添加和删除操作add和remove,一般大家都会说LinkedList要比ArrayList快,因为ArrayList要移动数据,但是实际情况可能会有差异。
  • 综上所述,在需要频繁读取集合中的元素时,使用ArrayList效率较高,而在插入和删除操作较多时,使用LinkedList效率较高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值