zoukankan      html  css  js  c++  java
  • 有关LinkedList常用方法的源码解析

    jdk1.7.0_79 

      上文里解析了有关ArrayList中的几个常用方法的源码——《有关ArrayList常用方法的源码解析》,本文将对LinkedList的常用方法做简要解析

      LinkedList是基于链表实现的,也就是说它具备了链表的优点和缺点,随机访问慢、插入删除速度快。既然是链表,那么它就存在节点数据结构,也不存在容量大小的问题,来一个在尾部添加一个。

    //LinkedList$Node
    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;
        }
    }

      第一个默认不带参数的构造方法,构造一个空链表。

    //1.LinkedList,默认构造方法
    public LinkedList() {
    }

      第二个构造方法能把一个集合作为一个参数传递,同时集合中的元素需要是LinkedList的子类

    //2.LinkedList,能将一个集合作为参数的构造方法
    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

      两个构造方法都比较简单,接下来看元素的插入及删除等方法。

    public boolean add(E e) {
        linkLast(e);    //将元素添加到链表尾部
        return true;
    }
    //LinkedList#linkLast
    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++;    //链表数据总数+1
        modCount++;    //modCount变量在《有关ArrayList常用方法的源码解析》提到过,增删都会+1,防止一个线程在用迭代器遍历的时候,另一个线程在对其进行修改。
    }

      学过《数据结构》的同学相信看到链表的操作不会感到陌生,接着来看看删除指定位置的元素remove(int)方法。

    //LinkedList#remove
    public E remove(int index) {
        checkElementIndex(index);    //检查是否越界 index >= 0 && index <= size
        return unlink(node(index));    //调用node方法查找并返回指定索引位置的Node节点
    }
    //LinkedList#node,根据索引位置返回Node节点
    Node<E> node(int index) {
        
        if (index < (size >> 1)) {    //size >> 1 = size / 2,如果索引位于链表前半部分,则移动fisrt头指针进行查找
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {    //如果索引位于链表后半部分,则移动last尾指针进行查找
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

      查找到index位置的Node,调用unlink方法摘掉该节点

    //LinkedList#unlink,一看即懂
    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;
    }

      从代码中就能看出LinkedListArrayList两者的优缺点,由于只涉及简单的链表数据结构,所以不再对其他方法进行解析。

  • 相关阅读:
    详解Python模块导入方法
    第15天上课例子,sqllchemy运用
    【Demo 0075】获取系统进程列表
    【Demo 0076】获取进程中模块列表
    【Demo 0071】托盘小工具
    【Demo 0070】读取EXE\DLL中ICON
    【Demo 0073】复合文件拼拆
    【Demo 0072】启动外部应用程序
    【Demo 0078】获取系统版本信息
    【Demo 0079】进程继承关系
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/7087175.html
Copyright © 2011-2022 走看看