• LinkedList源码详解


    LinkList概述

    LinkedList 是 List 接口链表的实现。基于双向链表实现的方式使得 LinkedList 在插入和删除时更优于 ArrayList,而随机访问则比 ArrayList 逊色些。
    但也是线程不安全

    这里写图片描述

    LinkList构造方法

        //构造一个空列表
        public LinkedList() {
        }
        //构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列。
        public LinkedList(Collection<? extends E> c) {
            this();
            addAll(c);
        }

        //将此列表中指定位置的元素替换为指定的元素。 
        public E get(int index) {
            //检查索引是否合法,检查规则:判断传入索引是否大于0和传入索引是否比当前列表的数量小
            checkElementIndex(index);
            //
            return node(index).item;
        }
        //查找结点,采用的是折半查找
        Node<E> node(int index) {
            // assert isElementIndex(index);
            //(size>>1)相当于除以2,
            //如果传入索引小于(size/2),那么从列表头开始查找
            if (index < (size >> 1)) {
                //将列表头的结点赋值给x
                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方法

    boolean add(E e),将指定元素添加到列表的结尾
    public boolean add(E e) {
            linkLast(e);//将元素e链接到列表末尾
            return true;
        }
    void linkLast(E e) {
            //last:最后一个结点,如果是第一次添加,last的初始值为NULL,将last赋值给l的
            final Node<E> l = last;
            //创建一个新的结点
            final Node<E> newNode = new Node<>(l, e, null);
            //将新的结点赋值给last
            last = newNode;
            //l==null成立说明:当前列表没有结点,添加到链表的第一个位置,链表头
            if (l == null)
                first = newNode;
            //不成立则说明:将新结点的引用赋值给上一个结点的后续元素
            else
                l.next = newNode;
            size++;
            modCount++;
        }   
    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;
            }
        }
    void add(int index, E element)

    指定的位置插入指定的元素。移动当前在该位置处的元素(如果有),所有后续元素都向右移(在其索引中添加 1)。

        public void add(int index, E element) {
            checkPositionIndex(index);
            //如果传入索引等于列表大小
            if (index == size)
                //往列表尾添加新的结点,跟add()方法一样
                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++;
        }

    删除指定索引元素

        public E remove(int index) {
            checkElementIndex(index);
            return unlink(node(index));
        }
        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;
        }

    迭代器

    因为Linkedlist多重继承了多个类,会先调用父类的方法,

    public ListIterator<E> listIterator() {
            //这里传递了一个0值
            return listIterator(0);
        }

    真正的有作用的方法是

        public ListIterator<E> listIterator(int index) {
            //判断index传入的值是否大于等于0与是否小于元素的大小
            checkPositionIndex(index);
            return new ListItr(index);
        }
    
       private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned = null;
        private Node<E> next;
        private int nextIndex;
        private int expectedModCount = modCount;
    
        ListItr(int index) {
            //取出链表头赋值给next
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }
    
    
    
        public boolean hasNext() {
            return nextIndex < size;
        }
    
        public E next() {
            checkForComodification();
            if (!hasNext())
                throw new NoSuchElementException();
    
            lastReturned = next;
            next = next.next;
            nextIndex++;
            return lastReturned.item;
        }
    
        public boolean hasPrevious() {
            return nextIndex > 0;
        }
    
        public E previous() {
            checkForComodification();
            if (!hasPrevious())
                throw new NoSuchElementException();
    
            lastReturned = next = (next == null) ? last : next.prev;
            nextIndex--;
            return lastReturned.item;
        }
    
        public int nextIndex() {
            return nextIndex;
        }
    
        public int previousIndex() {
            return nextIndex - 1;
        }
    
        public void remove() {
            checkForComodification();
            if (lastReturned == null)
                throw new IllegalStateException();
    
            Node<E> lastNext = lastReturned.next;
            unlink(lastReturned);
            if (next == lastReturned)
                next = lastNext;
            else
                nextIndex--;
            lastReturned = null;
            expectedModCount++;
        }
    
        //替换元素
        public void set(E e) {
            if (lastReturned == null)
                throw new IllegalStateException();
            checkForComodification();
            lastReturned.item = e;
        }
        //添加到当前索引的元素
        public void add(E e) {
            checkForComodification();
            lastReturned = null;
            if (next == null)
                linkLast(e);
            else
                linkBefore(e, next);
            nextIndex++;
            expectedModCount++;
        }
    
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
  • 相关阅读:
    StampedLock
    面试题:final关键字
    VTK 图像处理_显示(vtkImageViewer2 & vtkImageActor)
    VTK 图像处理_创建
    VTK 数据读写_图像数据的读写
    VTK 基本数据结构_如何把几何结构&拓扑结构加入到数据集
    VTK 基本数据结构_数据对象&数据集
    VTK 可视化管道的连接与执行
    VTK 坐标系统及空间变换(窗口-视图分割)
    VTK 三维场景基本要素:相机
  • 原文地址:https://www.cnblogs.com/aotemanzhifu/p/9192374.html
Copyright © 2020-2023  润新知