3.2.5 Link子接口-LinkedList

Link-子接口LinkedList


LinkedList基本:
  1. 底层实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可重复),包括null
  3. 线程不安全,没有实现同步

比较 ArrayList和LinkedList :
LinkedList类是List接口的实现类,它是一个集合,可以根据索引来随机的访问集合中的元素,还实现了Deque接口,它还是一个队列,可以被当成双端队列来使用。虽然LinkedList是一个List集合,但是它的实现方式和ArrayList是完全不同的,ArrayList的底层是通过一个动态的Object[]数组来实现的,而LinkedList的底层是通过链表来实现的,因此它的随机访问速度是比较差的,但是它的删除,插入操作会很快。

ArrayList:

基于数组,在数组中搜索和读取数据是很快的。因此 ArrayList 获取数据的时间复杂度是O(1);
但是添加、删除时该元素后面的所有元素都要移动,所以添加/删除数据效率不高;
另外其实还是有容量的,每次达到阈值需要扩容,这个操作比较影响效率。

LinkedList:

基于双端链表,添加/删除元素只会影响周围的两个节点,开销很低;
只能顺序遍历,无法按照索引获得元素,因此查询效率不高;
没有固定容量,不需要扩容;
需要更多的内存,LinkedList 每个节点中需要多存储前后节点的信息,占用空间更多些。

LinkedList的底层操作机制 :
  1. LinkedList 底层维护了一个双向链表
  2. LinkedList中维护了两个属性 firstlast,分别指向首节点和尾节点
  3. 每个节点(Node对象),里面有维护了prev,next,item三个属性,实现双向链表
  • 简单的一个双向链表:


模拟一个简单的双向链表
/**
 * 模拟双向链表
 */
public class LinkedList_doubleLink {
    public static void main(String[] args) {

        Node n1 = new Node("item01");
        Node n2= new Node("item02");
        Node n3 = new Node("item03");

        n1.next = n2;
        n2.pre = n1;
        n2.next = n3;
        n3.pre = n2;

        // 头节点 和 尾节点
        Node first = n1;
        Node last = n3;


        // while 循环 让first指向下一个节点
        // 从头到尾
        System.out.println("===从头到尾===");
        while (true){
            if (first == null){
                break;
            }
            System.out.println(first);
            first = first.next;
        }

        // 从尾到头
        System.out.println("===从尾到头===");
        while (true){
            if (last == null){
                break;
            }
            System.out.println(last);
            last = last.pre;
        }

        // 插入 一个节点
        // 在n1 和 n2 中间插入一个 m节点
        Node m = new Node("插入m");

        n1.next = m;
        m.pre = n1;
        m.next = n2;
        n2.pre = m;

        System.out.println("==插入节点后==");
        first = n1;
        while (true){
            if (first == null){
                break;
            }
            System.out.println(first);
            first = first.next;
        }


    }
}

// 定义一个Node类,Node对象表示一个节点
class Node{
    public Object item;
    public Node next;
    public Node pre;

    public Node(Object name) {
        this.item = name;
    }

    @Override
    public String toString() {
        return "Node name :" + item;
    }
}

LinkedList底层结构
  • add(E e) // 在链表后添加一个新元素 通用方法
 
public boolean add(E e) {
        linkLast(e); // 实现的主要方法 
        return true;
    }
/**
     * Links e as last element.
     */
    void linkLast(E e) {
        final Node<E> l = last;   // 创建一个指向尾节点的指针  
        final Node<E> newNode = new Node<>(l, e, null);  // 创建一个新节点 
        last = newNode;  // last应用指向新的节点
        if (l == null)  
            first = newNode;
        else
            l.next = newNode;  // 当前尾节点的 next 指向 新的尾节点
        size++;
        modCount++;
  • remove() :移除链表中第一个元素; 通用方法
public E remove() {
        return removeFirst();
    }
public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);   // 主要靠这个实现移除
    }
 private E unlinkFirst(Node<E> f) {
        // assert f == first && f != null;
        final E element = f.item;  // 将要移除的头节点的信息赋给element,方便最后返回,留用处理。
        final Node<E> next = f.next;  
        f.item = null;
        f.next = null; // 断开头节点和下一个节点的尾链接
        first = next;  // 将头指针对象 指向下一个节点
        if (next == null)
            last = null;
        else
            next.prev = null;   // 下一个节点断开与头节点的头链接
        size--;   // 链表减一
        modCount++;
        return element;
    }

引用博文补充


常用方法
  • 增加:
    
    add(E e):在链表后添加一个元素;   通用方法
    addFirst(E e):在链表头部插入一个元素;  特有方法
    addLast(E e):在链表尾部添加一个元素;  特有方法
    push(E e):与addFirst方法一致  
    offer(E e):在链表尾部插入一个元素
    add(int index, E element):在指定位置插入一个元素。      
    offerFirst(E e):JDK1.6版本之后,在头部添加; 特有方法                
    offerLast(E e):JDK1.6版本之后,在尾部添加; 特有方法
    
    删除:
    remove() :移除链表中第一个元素;    通用方法  
    remove(E e):移除指定元素;   通用方法
    removeFirst(E e):删除头,获取元素并删除;  特有方法
    removeLast(E e):删除尾;  特有方法
    pollFirst():删除头;  特有方法
    pollLast():删除尾;  特有方法
    pop():和removeFirst方法一致,删除头。 
    poll():查询并移除第一个元素     特有方法    
    
    查:
    
    get(int index):按照下标获取元素;  通用方法
    getFirst():获取第一个元素;  特有方法
    getLast():获取最后一个元素; 特有方法
    peek():获取第一个元素,但是不移除;  特有方法
    peekFirst():获取第一个元素,但是不移除; 
    peekLast():获取最后一个元素,但是不移除;
    pollFirst():查询并删除头;  特有方法
    pollLast():删除尾;  特有方法
    poll():查询并移除第一个元素     特有方法
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值