LinkedList源码分析

1. 源码分析
// LinkedList 源码

// list中实际存储元素的个数
transient int size = 0;

// 头节点
transient Node<E> first;

// 尾节点
transient Node<E> last;

// 添加一个元素
public boolean add(E e) {
    linkLast(e);
    return true;
}

//list尾插入   
void linkLast(E e) {
    final Node<E> l = last;   //保存尾节点
    final Node<E> newNode = new Node<>(l, e, null);   //创建一个节点  设置前置节点为尾巴节点,节点值为当前元素,后置节点为空
    last = newNode;   //由于尾插入  所以新节点变为尾节点
    if (l == null)     //如果插入的时候list没有尾巴,说明list为空,
        first = newNode;   //则新元素又是头节点又是尾节点
    else   
        l.next = newNode;   //否则让原来的尾节点的下一个节点为新增节点
    size++;    //记录长度+1
    modCount++;     //增加modCount
}

//节点构造器
Node(Node<E> prev, E element, Node<E> next) {
    this.item = element;
    this.next = next;
    this.prev = prev;
}
  • ArrayList相比,LinkedList插入或删除元素时无需判断是否需要扩容,也同时免去扩容耗时,所以它的插入删除性能更高。

  • 但由于ArrayList底层是一个数组,所以它可以精准的通过get(index)方法来获取指定位置上的元素。

由于LinkedList底层是一个链表,所以当使用get(index)方法时,只能一个一个的遍历找到相应位置的元素。

那么对于精准查找来说,ArrayList的性能更优。

//LinkedList 获取指定位置元素    源码

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

//ArrayList 获取指定位置元素   源码
public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}

E elementData(int index) {
    return (E) elementData[index];    //直接取得
}
  • 而对于他们的遍历性能来说,是相同的。

所以在频繁插入和删除的场景下,应该选择LinkedList,而在需要精准定位的场景下,使用ArrayList

2. 可能出现的问题

ArrayList相同,LinkedList在添加和删除元素时,会修改modCount自增。那么在迭代器操作时,如果发现了modCount已经被改变,则会抛出ConcurrentModificationException

自此说明,ArrayListLinkedList都是不保证线程安全的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值