zoukankan      html  css  js  c++  java
  • Java-链表LinkedList源码原理分析,并且通过LinkedList构建队列

    在这里我们介绍一下最简单的链表LinkedList;

    看一下add()方法:

    public boolean add(E e) {
            linkLast(e);
            return true;
        }
    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++;
            modCount++;
        }

    add原理就是:

    1.首先获取链表最后一个节点。

    2.把新节点插入到最后一个节点之后。

    3.linkedList的last属性重新指向最后一个节点。

    4.如果这个节点是第一个节点,之前没有节点,那么将linkedList的first的属性指向新节点;如果不是,则将上一个节点的next属性指向该节点。

    使用LinkedList构建先进先出队列:

    offer()方法入队:使用add()方法插入节点在最后。

    public boolean offer(E e) {
            return add(e);
        }

    poll()方法出队:从链表表头开始移出队列

    public E poll() {
            final Node<E> f = first;
            return (f == null) ? null : unlinkFirst(f);
        }

    使用LinkedList构建后进先出队列:

    push()方法入队:插入节点在first

    public void addFirst(E e) {
            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++;
        }

    pop()方法出队:从链表表头开始移出队列

    public E pop() {
            return removeFirst();
        }
    
    public E removeFirst() {
            final Node<E> f = first;
            if (f == null)
                throw new NoSuchElementException();
            return unlinkFirst(f);
        }
    
    private E unlinkFirst(Node<E> f) {
            // assert f == first && f != null;
            final E element = f.item;
            final Node<E> next = f.next;
            f.item = null;
            f.next = null; // help GC
            first = next;
            if (next == null)
                last = null;
            else
                next.prev = null;
            size--;
            modCount++;
            return element;
        }

    最后需要注意的是:LinkedList是线程不安全的,如果需要线程安全那么请使用synchronized加锁,或者使用vector,或者使用java.util.concurrent包。

    如果需要线程遍历List的时候,避免出现ConcurrentModificationException异常,那么有3种解决方式。

    1.遍历List的使用synchronized加锁;

    2.使用java.util.concurrent包下面的CopyOnWriteArrayList,每次使用List时实际上都是使用的List副本。

    3.使用Jdk8中foreach方法,不过该方法只接受lambda表达式

    list.forEach(item -> {
                        System.out.println("遍历元素:" + item);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    });
  • 相关阅读:
    Linux目录
    find命令
    107. Binary Tree Level Order Traversal II
    grep命令
    110. Balanced Binary Tree
    111. Minimum Depth of Binary Tree
    什么是泛型
    自动装箱与拆箱
    HDU 3001 Travelling (状压DP + BFS)
    POJ 3411 Paid Roads (状态压缩+BFS)
  • 原文地址:https://www.cnblogs.com/eoss/p/5948868.html
Copyright © 2011-2022 走看看