• java容器类:LinkedList


    作为一个新手,我几乎没有在任何情况下使用过LinkedList,唯一用到的就是和ArrayList比较.但是这并不妨碍我学习它.LinkedList是双向链表的一个经典实现.作为一个链表,它的优点是显而易见的

    • 采用动态存储,可以使用不连续的内存空间(数组要求连续),因此提高了内存的利用率.
    • 插入和删除元素十分方便,只需要修改指针即可,不需要移动大量元素(数组需要).

    从增删改查方面入手,我们很快就能了解到LinkedList是怎么实现的.

    找到源码中的add方法

    public boolean add(E e) {
        linkLast(e);//调用linkLast方法,从字面上来讲是将实例对象e加入尾部
        return true;
    }
    
    void linkLast(E e) {
        final Node<E> l = last;//Node是LinkedList的内部类,用以表示链表内的节点,last表示LinkedList内的空的最后一个节点
        final Node<E> newNode = new Node<>(l, e, null);//构造一个存有对象e的实例,以l即last为头节点,尾节点为null
        last = newNode;//此时newNode成为链表的最后一个节点
        if (l == null)//如果l为空,说明之前LinkedList是空的,所以newNode既是第一个节点,也是最后一个节点
            first = newNode;
        else
            l.next = newNode;//不然就贯通双向链表,将l节点的指针指向newNode
        size++;
        modCount++;
    }
    

    简单来讲,就是把构造一个newNode对象,与last对象相连并置于last之后,这样newNode就成了新的last节点.这个时候,就要根据newNode是不是第一个加入的节点.如果不是,就把原来的last结点指向newNode节点,形成双向链表.注意final关键字.

    同样地还有linkFirst方法,从头部加入对象e

    private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }
    

    remove方法

    public boolean remove(Object o) {//因为非空对象才能使用equals方法,所以需要进行判断
        //通过遍历得到符合要求的对象,使用unlink方法进行删除.
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null) {
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }
    
    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节点的位置
            first = next;
        } else {
            prev.next = next;//将头节点指向尾节点,就是绕过要删除的这个节点产生新的链
            x.prev = null;//释放该节点储存的头节点信息
        }
    
        if (next == null) {
            last = prev;//判断尾节点如果为空,那么确定last节点的位置
        } else {
            next.prev = prev;//将尾节点指向头节点,到这一步两个节点双向打通
            x.next = null;//释放该节点储存的尾节点信息
        }
    
        x.item = null;//到此释放要删除节点的所有内容
        size--;
        modCount++;
        return element;
    }
    

    get方法
    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;
        }
    }
  • 相关阅读:
    您还在用下一步下一步的方式安装SQLSERVER和SQLSERVER补丁吗?
    SQLSERVER误删除了Windows登录用户验证方式使用Windows身份验证的解决方法
    批量解密SQLSERVER数据库中的各种对象的工具dbForge SQL Decryptor
    SQLSERVER将数据移到另一个文件组之后清空文件组并删除文件组
    SQLSERVER群集故障转移笔记
    兼容,原来在这里就已经開始--------Day34
    Objective-C的对象模型和runtime机制
    CF B. Kolya and Tandem Repeat
    循环队列的实现
    LintCode 子树
  • 原文地址:https://www.cnblogs.com/itsrobin/p/5188359.html
Copyright © 2020-2023  润新知