zoukankan      html  css  js  c++  java
  • LinkedList源码阅读笔记

    LinkedList

      底层是双向链表,可当作堆栈、队列或双端队列,元素可以为null,理论上对元素个数没有限制。线程不安全,如果多个线程同时访问一个链表,并至少一个线程进行结构性修改,它必须保持外部同步。(结构上的修改是指添加或删除一个或多个元素的操作,仅设置元素的值不是结构修改。)List list = Collections.synchronizedList(new LinkedList(...));

    常用方法

            LinkedList<String> linkedList = new LinkedList<>();
            linkedList.add("a");              // 添加到链表尾部
            linkedList.addLast("last");       // 添加到链表尾部(等同于add)
            linkedList.offer("last_last");    // 添加到链表尾部
            linkedList.offerLast("last_last_last"); // 添加到链表尾部
            linkedList.add(1,"b");                  // 指定索引添加元素,其他元素后移
    
            ArrayList<String> arrayList = new ArrayList<>();
            arrayList.add("arr_list1");
            arrayList.add("arr_list2");
            linkedList.addAll(arrayList);           // 将指定Collection实现类的对象中的元素依次添加到尾部
            linkedList.addAll(1,arrayList);         // 将指定Collection实现类的对象中的元素依次添加到指定索引
    
            linkedList.size();                      // 返回元素个数
    
            linkedList.addFirst("first");           // 添加到链表头部
            linkedList.offerFirst("first_first");   // 添加到链表头部
            
            linkedList.set(0,"aaa");      // 设置指定索引的元素
            linkedList.get(1);            // 获取指定索引的元素
            linkedList.contains("a");     // 判断是否包含指定元素
            
            linkedList.indexOf("a");       // 获取指定元素的第一个索引
            linkedList.lastIndexOf("a");   // 获取指定元素的最后一个索引
            
            linkedList.element();      // 获取链表头元素(但不移除)
            linkedList.getFirst();     // 获取第一个元素(但不移除)
            linkedList.peek();         // 获取第一个元素(但不移除)
            linkedList.peekFirst();    // 获取第一个元素(但不移除)
            linkedList.poll();         // 获取第一个元素(并移除)
            linkedList.pollFirst();    // 获取第一个元素(并移除)
            linkedList.remove();       // 移除并返回第一个元素
            linkedList.removeFirst();  // 移除并返回第一个元素
            
            linkedList.pop();          // 移除第一个元素
            
            linkedList.peekLast();     // 获取最后一个元素(但不移除)
            linkedList.pollLast();     // 获取最后一个元素(并移除)
            linkedList.getLast();      // 获取链表最后一个元素(但不移除)
            linkedList.removeLast();   // 移除并返回最后一个元素
            linkedList.push("aaaaa");  // 添加到头部
            linkedList.remove("aaaaa"); // 移除指定元素
            
            linkedList.removeLastOccurrence("last"); // 移除最后一次出现的指定元素
            linkedList.removeFirstOccurrence("b");   // 移除第一次出现的指定元素
    
            Object[] arr;
            arr = linkedList.toArray();    // 转化为数组
    
            linkedList.toArray(arr);       // 转化为数组
    
    
            ListIterator listIterator = linkedList.listIterator(); // 返回迭代器
            while (listIterator.hasNext()) {
                System.out.println(listIterator.next());
            }
    
            Iterator listIterator1 = linkedList.descendingIterator(); // 返回倒序迭代器
            while (listIterator1.hasNext()) {
                System.out.println(listIterator1.next());
            }

    源码阅读

      继承了AbstractSequentialList<E>,实现了implements List<E>, Deque<E>, Cloneable, java.io.Serializable接口。

    字段

        transient int size = 0;   // 链表结点数
        transient Node<E> first;  // 指向头结点
        transient Node<E> last;   // 指向尾结点

    构造器

        // 构造一个空链表
        public LinkedList() {
        }
    
    
        // 用指定的Collection实现类对象中元素构造
        public LinkedList(Collection<? extends E> c) {
            this();
            addAll(c);
        }

    内部类Node类

        private static class Node<E> {
            E item;
            Node<E> next;
            Node<E> prev;
    
         // 构建新结点需指定prev域和next域
            Node(Node<E> prev, E element, Node<E> next) {
                this.item = element;
                this.next = next;
                this.prev = prev;
            }
        }

    方法

      // 将e链接为第一个元素
        private void linkFirst(E e) {
            final Node<E> f = first;
        // 作为第一个元素,其prev域需是null
            final Node<E> newNode = new Node<>(null, e, f);
            first = newNode;
            if (f == null)
                last = newNode;
            else
                f.prev = newNode;
            size++;
            modCount++;
        }
    
      // 将e链接为最后一个元素
        void linkLast(E e) {
            final Node<E> l = last;
        // 作为第一个元素,其next域需是null
            final Node<E> newNode = new Node<>(l, e, null);
            last = newNode;
            if (l == null)
                first = newNode;
            else
                l.next = newNode;
            size++;
            modCount++;
        }
      // 将结点e插入到succ结点之前
        void linkBefore(E e, Node<E> succ) {
            final Node<E> pred = succ.prev;
         // 新结点的prev域和next域分别是pred和succ
            final Node<E> newNode = new Node<>(pred, e, succ);
            succ.prev = newNode;        // 使succ的向前指针指向新结点
            if (pred == null)           // 之前的链表只有一个结点
                first = newNode;
            else
                pred.next = newNode;  // succ原来的前一个结点指向新结点
            size++;
            modCount++;
        }

    本方法图示:

      // 将f不再链接为第一个元素
        private E unlinkFirst(Node<E> f) {
            final E element = f.item;
            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;
        }
    
      // 将l不再链接为最后一个元素
        private E unlinkLast(Node<E> l) {
            final E element = l.item;
            final Node<E> prev = l.prev;
            l.item = null;
            l.prev = null; // help GC
            last = prev;
            if (prev == null)
                first = null;
            else
                prev.next = null;
            size--;
            modCount++;
            return element;
        }
    
      // 将结点x解除链接
        E unlink(Node<E> x) {
            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;
        }
    
      // 移除头结点
        public E removeFirst() {
            final Node<E> f = first;
            if (f == null)
                throw new NoSuchElementException();
            return unlinkFirst(f);
        }
    
      // 移除尾结点
        public E removeLast() {
            final Node<E> l = last;
            if (l == null)
                throw new NoSuchElementException();
            return unlinkLast(l);
        }
    
      // 移除指定对象
        public boolean remove(Object o) {
            if (o == null) {                 // null元素单独处理
                for (Node<E> x = first; x != null; x = x.next) {
                    if (x.item == null) {     // 用“==”
                        unlink(x);
                        return true;
                    }
                }
            } else {                       // 非null元素
                for (Node<E> x = first; x != null; x = x.next) {
                    if (o.equals(x.item)) {   // 用“equals”
                        unlink(x);
                        return true;
                    }
                }
            }
            return false;
        }
    
        public void clear() {
            for (Node<E> x = first; x != null; ) {
                Node<E> next = x.next;   // 保存后一个结点
                x.item = null;            // 本结点全部置null
                x.next = null;
                x.prev = null;
                x = next;                   // 移到下一个结点
            }
            first = last = null;
            size = 0;
            modCount++;
        }
    
      // 插入元素到指定位置
        public void add(int index, E element) {
            checkPositionIndex(index);
    
            if (index == size)        // 插入位置是最后
                linkLast(element);
            else                // 插入到指定元素前(是插入元素成为那个位置的元素)
                linkBefore(element, node(index));   
      }
      // 返回指定位置的元素
        Node<E> node(int 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;
            }
        }
    
      // 获取指定索引的元素
        public E get(int index) {
            checkElementIndex(index);
            return node(index).item;
        }
  • 相关阅读:
    织网的日子里——第一章:TCP时间获取之客户端和服务器端程序
    Hdu 4517 小小明系列故事——游戏的烦恼
    MongoDB安装配置
    【算法学习】线性时间排序计数排序、基数排序和桶排序详解与编程实现
    C++中宏的使用技巧
    每三小时热备shell脚本文件
    OSS音频编程实例
    MySQL的Illegal mix of collationsy异常原因和解决方法
    SQL用了Union后的排序问题
    union 时只能查出一个表中的信息,另一个表只能查出字段
  • 原文地址:https://www.cnblogs.com/jiazhongxin/p/12860055.html
Copyright © 2011-2022 走看看