• LinkedList源码学习


     

    链表数据结构

      当前节点会保存上一个、下一个节点。 参见 LinkedList的Node类

      实现:
        1. 内部链表的方式。
          1.1 添加元素。追加的方式,创建一个新的节点[Node],用最后一个节点关联新的节点。
          1.2 删除元素
            1.2.1 通过对象删除。遍历链表,删除第一个匹配的对象
                修改链表关联结构
        2. 内部是同步[modCount]
          2.1 LinkedList数据结构变化的时候,都会将modCount++。
          2.2 采用Iterator遍历的元素, next()会去检查集合是否被修改[checkForComodification],如果集合变更会抛出异常
            类似于数据库层面的 乐观锁 机制。 可以通过 Iterator的api去删除元素
        3. 数组结构,内部存储数据是有序的,并且数据可以为null

    源码实现

    package xin.rtime.collections.list;
    
    import java.util.ConcurrentModificationException;
    import java.util.Iterator;
    import java.util.ListIterator;
    import java.util.NoSuchElementException;
    
    // 链表的源码实现
    public class LinkedList<E> {
    
        transient int size = 0;  // 当前链表的size
        
        transient Node<E> first;  // 首节点
        
        transient Node<E> last;   // 尾节点
        
        private int modCount = 0;  // 结构修改次数
        
        // 添加节点
        public boolean add(E e) {
            linkLast(e);
            return true;
        }
        
        // 删除节点
        public boolean remove(Object o) {
            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)) {   // equals
                        unlink(x);
                        return true;
                    }
                }
            }
            return false;
        }
        
        // 获取节点
        public E get(int index) {
            checkElementIndex(index);  // 检查元素Index是否存在 , 不存在会抛出数组越界
            return node(index).item;
        }
        
        // 获取链表size
        public int size() {
            return size;
        }
        
        public Iterator<E> iterator() {
            return listIterator();
        }
        
        public ListIterator<E> listIterator() {
            return listIterator(0);
        }
        
        Node<E> node(int index) {
            // assert isElementIndex(index);
    
            if (index < (size >> 1)) {   // 当前index 小于 当前一半容量的 size
                Node<E> x = first;  // 当前节点  等于 首节点
                for (int i = 0; i < index; i++)   // 遍历  index -1 次
                    x = x.next;   // x 等于当前节点的下一个节点
                return x;
            } else { // 大于
                Node<E> x = last;
                for (int i = size - 1; i > index; i--)   // 从尾部开始遍历
                    x = x.prev;  //  x 等于当前节点的上一个节点
                return x;
            }
        }
        
        private void checkElementIndex(int index) {
            if (!isElementIndex(index))   // 节点index是否在链表的容量范围内
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
        private boolean isElementIndex(int index) {
            return index >= 0 && index < size;
        }
        
        private String outOfBoundsMsg(int index) {
            return "Index: "+index+", Size: "+size;
        }
        
        // 获得首个节点值
        public E getFirst() {
            final Node<E> f = first;
            if (f == null)
                throw new NoSuchElementException();
            return f.item;
        }
        
        // 获得尾部节点值
        public E getLast() {
            final Node<E> l = last;
            if (l == null)
                throw new NoSuchElementException();
            return l.item;
        }
        
        // 获得所有节点值
        public Object[] toArray() {
            Object[] result = new Object[size];
            int i = 0;
            for (Node<E> x = first; x != null; x = x.next)
                result[i++] = x.item;
            return result;
        }
        
        public ListIterator<E> listIterator(int index) {
            checkPositionIndex(index);
            return new ListItr(index);
        }
    
        private void checkPositionIndex(int index) {
            if (!isPositionIndex(index))
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }
    
        // 判断当前节点index是否存在
        private boolean isPositionIndex(int index) {
            return index >= 0 && index <= size;
        }
        
        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) {
                // assert isPositionIndex(index);
                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)  // 下一个节点为null
                    linkLast(e);   // 在尾部插入
                else
                    linkBefore(e, next);  // 在指定节点之前插入
                nextIndex++;
                expectedModCount++;
            }
    
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
            }
        }
        
        private 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;  // 当前节点的上一个节点置为null  gc回收
             }
    
             if (next == null) {   // 下一个节点为空
                 last = prev;   // 最后节点 = 当前节点的上一个节点
             } else {  // 不为空 
                 next.prev = prev;  // 上一个节点的上一个节点   等于  当前节点的上一个节点
                 x.next = null;  // 当前节点的下一个节点置为null  gc回收
             }
    
             x.item = null;  // 当前元素置为null  gc回收
             size--;  // 长度 + 1
             modCount++;  // 修改次数+1
             return element;
        }
    
        // 在链表的尾部插入节点
        void linkLast(E e) {
            final Node<E> l = last;  // 最后一个元素
            final Node<E> newNode = new Node<>(l, e, null);  // 上一个元素,当前元素,null
            last = newNode;  // 最后一个节点等新建的节点
            if (l == null)  // 如果最后一个节点为空
                first = newNode;    // 出现一个情况:  当链表为空的时候 , first 和 last 都为 newNode
            else
                l.next = newNode;   //最后节点的下一个节点,等于当前节点
            size++;  // 链表长度+1
            modCount++;  // 修改次数+1
        }
        
        // 在指定节点添加上一个节点
        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++;
        }
    
        // 链表节点
        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;
            }
        }
    }
  • 相关阅读:
    Oracle:SQL语句--对表的操作——修改列的数据类型( 即 修改字段的数据类型)
    Oracle:SQL语句--对表的操作——修改列的数据类型( 即 修改字段的数据类型)
    有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和
    有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和
    鸡兔同笼:笼子里一共有鸡和兔子35只,一共有94条退, 笼子里一共有鸡和兔子共多少只
    jQuery,使用on代替delegate,live 写法区别
    安卓手机微信页面position: fixed位置错误
    表单提交是ajax提交,PC提交没问题但是手机提交就会一直跳到error,并且也没状态码一直是0
    新版本的jquery checkbox 全选反选代码只能执行一遍,第二次就失败attr与prop区别
    倒计时js代码
  • 原文地址:https://www.cnblogs.com/LuisYang/p/10034601.html
Copyright © 2020-2023  润新知