java数据结构之LinkedList

一、LinkedList源码注释

//LinkedList源码  jdk版本1.8.0_121
public class LinkedList<E> extends AbstractSequentialList<E>  implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    transient int size = 0;

    /**
     * 指向第一节点
     * first和last要么都为null,要么都不为null。不要把节点node和节点的item混淆
     */
    transient Node<E> first;

    /**
     * 指向最后一个节点
     */
    transient Node<E> last;

    /**
     * 构造一个空的LinkedList
     */
    public LinkedList() {
    }

    /**
     * 通过集合来构建LinkedList
     */
    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    /**
     * 将元素放在第一个位置
     * 具体做法就是创建一个新的节点newNode,newNode的item设置为该元素,然后newNode的next指向原来的第一个节点
     * 将first指向新的节点,如果是第一次添加节点就将last也指向该节点,如果不是第一次添加就将原来的第一个节点的prev指向新的节点
     */
    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++;
    }

    /**
     * 将元素放在最后一个位置
     * 创建一个新的节点newNode,将newNode的prev指向原来的最后一个节点
     * 将last指向newNode,如果是第一次添加就将first也指向newNode,如果不是第一次添加就将原来最后一个节点的next指向newNode
     */
    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++;
    }

    /**
     * 将元素插入到另外一个节点的前面
     * 根据元素创建一个新的节点newNode,newNode的prev指向另一个节点succ的prev所指向的节点,newNode的next指向succ
     * 如果succ的prev为null,也就是说我succ为第一个节点,那么要将fisrt指向newNode,如果succ不是第一个节点,那么就让succ的prev所指向的节点的next指向newNode
     */
    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++;
    }

    /**
     * 将节点从第一个位置上移除
     * 将第一个元素的item和next都置为null,方便垃圾回收
     * first指向将next指向的节点,如果next指向的节点为null,就将last也设置为null(也就是说这个要移除的节点是链表中的最后一个节点)
     * 如果next指向的节点不为null,那么就将next指向的节点的prev设置为null
     */
    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;
    }

    /**
     * 移除最后一个元素
     * 将最后一个元素的item和prev置为null,它的last本来就为null所以不用管
     * 然后将last指向prev指向的节点,如果prev指向的节点为null,那么就将first也设置为null(也就是说这个要移除的节点是链表中的最后一个节点)
     * 如果prev指向的节点不为null,那么就将prev指向节点的next设置为null
     */
    private E unlinkLast(Node<E> l) {
        // assert l == last && l != null;
        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;
    }

    /**
     * 移除一个节点
     * 如果该节点是第一个节点,就将first指向该节点的下一个节点,否则将该节点的上一个节点的next指向该节点的下一个节点
     * 如果该节点是最后一个节点,就将last指向该节点的上一个节点,否则就将下一个节点的prev指向该节点的上一个节点
     * 将当前的接电点的prev、item、next都置为null,方便GC
     */
    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;
    }

    /**
     * 获取list中的第一个元素,直接通过first节点,获取其中的item,如果是空list会报错
     */
    public E getFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

    /**
     * 获取list中的最后一个元素,直接通过last来获取,如果是空list会报错
     */
    public E getLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

    /**
     * 删除第一个节点,如果是空list会报错
     */
    public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }

    /**
     * 删除最后一个节点,如果是空list会报错
     */
    public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

    /**
     * 将元素加入到list最前面
     */
    public void addFirst(E e) {
        linkFirst(e);
    }

    /**
     * 将元素加入到list最后面
     */
    public void addLast(E e) {
        linkLast(e);
    }

    /**
     * 判断list是否包含该对象
     */
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

    /**
     * 返回元素的个数
     */
    public int size() {
        return size;
    }

    /**
     * 将元素添加到LinkedList尾部
     */
    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)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 批量加入集合中的元素到list尾部
     */
    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

    /**
     * 批量加入集合中的元素到list的index处
     */
    public boolean addAll(int index, Collection<? extends E> c) {
        checkPositionIndex(index);
        //如果传入的集合中元素个数为0,直接返回false
        Object[] a = c.toArray();
        int numNew = a.length;
        if (numNew == 0)
            return false;

        Node<E> pred, succ;//pred 是指向插入的第一个元素的前一个节点,succ是指向插入的 最后一个元素的后一个节点
        if (index == size) {//如果index为size那就说明是插在最后一个元素的后面
            succ = null;
            pred = last;
        } else {
            succ = node(index);
            pred = succ.prev;
        }
        //循环将集合中的元素加入到list中
        for (Object o : a) {
            @SuppressWarnings("unchecked") E e = (E) o;
            Node<E> newNode = new Node<>(pred, e, null);
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            pred = newNode;
        }
        //如果succ为null,则将last指向最后添加的元素,如果不为null则和加入的最后一个元素关联起来
        if (succ == null) {
            last = pred;
        } else {
            pred.next = succ;
            succ.prev = pred;
        }

        size += numNew;
        modCount++;
        return true;
    }

    /**
     * 清空LinkedList中所有的数据
     * 这里循环清空了所有节点之间的联系,虽然这不是必须的,但是这样做会有助于分代GC
     */
    public void clear() {
        // Clearing all of the links between nodes is "unnecessary", but:
        // - helps a generational GC if the discarded nodes inhabit
        //   more than one generation
        // - is sure to free memory even if there is a reachable Iterator
        for (Node<E> x = first; x != null; ) {
            Node<E> next = x.next;
            x.item = null;
            x.next = null;
            x.prev = null;
            x = next;
        }
        first = last = null;
        size = 0;
        modCount++;
    }

    // Positional Access Operations 位置相关的一些操作,也就是和下标index有关

    /**
     * 获取某个下标处的元素
     */
    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }

    /**
     * 设置某个下标处的元素
     */
    public E set(int index, E element) {
        checkElementIndex(index);
        Node<E> x = node(index);
        E oldVal = x.item;
        x.item = element;
        return oldVal;
    }

    /**
     * 在某个下标处添加一个元素
     */
    public void add(int index, E element) {
        checkPositionIndex(index);

        if (index == size)//添加在最后面
            linkLast(element);
        else
            linkBefore(element, node(index));
    }

    /**
     * 删除某个下标处的元素
     */
    public E remove(int index) {
        checkElementIndex(index);
        return unlink(node(index));
    }

    /**
     * 判断下标处有没有元素
     */
    private boolean isElementIndex(int index) {
        return index >= 0 && index < size;
    }

    /**
     * 判断这个index是否可以用于添加或者迭代,和上面的相比只是多了一个size值。
     */
    private boolean isPositionIndex(int index) {
        return index >= 0 && index <= size;
    }

    /**
     * 越界异常语句
     */
    private String outOfBoundsMsg(int index) {
        return "Index: "+index+", Size: "+size;
    }

    private void checkElementIndex(int index) {
        if (!isElementIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private void checkPositionIndex(int index) {
        if (!isPositionIndex(index))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    /**
     * 返回index处非null的节点,index 小于 size的一半就从前面开始查找,否则从后面开始查找
     */
    Node<E> node(int index) {
        // assert isElementIndex(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;
        }
    }

    // Search Operations

    /**
     * 查找该对象在list中的下标,第一次出现的下标,没有返回-1
     */
    public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null)
                    return index;
                index++;
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }

    /**
     * 返回对象在list中最后一次出现的下标
     */
    public int lastIndexOf(Object o) {
        int index = size;
        if (o == null) {
            for (Node<E> x = last; x != null; x = x.prev) {
                index--;
                if (x.item == null)
                    return index;
            }
        } else {
            for (Node<E> x = last; x != null; x = x.prev) {
                index--;
                if (o.equals(x.item))
                    return index;
            }
        }
        return -1;
    }

    // Queue operations.队列的相关操作,先进先出

    /**
     * 返回list第一个元素,没有元素不会报错
     */
    public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }

    /**
     * 返回list中第一个元素,list为空会报错
     */
    public E element() {
        return getFirst();
    }

    /**
     * 返回并删除list中第一个元素,list为空不会报错
     */
    public E poll() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

    /**
     * 删除并返回第一个list中的元素,list为空会报错
     */
    public E remove() {
        return removeFirst();
    }

    /**
     * 新增一个元素到list尾部
     */
    public boolean offer(E e) {
        return add(e);
    }
    //Queue operations  end

    // Deque operations   双端队列的 一些操作
    /**
     * 在队列的 最前端加入一个元素
     */
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }

    /**
     * 在队列的 最后端加入一个元素
     */
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }

    /**
     * 获取队列的第一个元素
     */
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
     }

    /**
     * 获取队列的最后一个元素
     */
    public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }

    /**
     * 返回并删除队列中的第一个元素
     */
    public E pollFirst() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

    /**
     * 返回并删除队列中的最后一个元素
     */
    public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }

    // Deque operations end

    //stack operations  出栈和入栈的 一些相关操作。
    /**
     * 向栈中压入一个元素
     */
    public void push(E e) {
        addFirst(e);
    }

    /**
     * 从栈中弹出一个元素,栈为空会报错
     */
    public E pop() {
        return removeFirst();
    }

    //stack operations end

    /**
     * 删除该对象第一次出现的节点
     */
    public boolean removeFirstOccurrence(Object o) {
        return remove(o);
    }

    /**
     * 删除该对象最后一个出现的节点
     */
    public boolean removeLastOccurrence(Object o) {
        if (o == null) {
            for (Node<E> x = last; x != null; x = x.prev) {
                if (x.item == null) {
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node<E> x = last; x != null; x = x.prev) {
                if (o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取list迭代器
     */
    public ListIterator<E> listIterator(int index) {
        checkPositionIndex(index);
        return new ListItr(index);
    }

    private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned;
        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)
                linkLast(e);
            else
                linkBefore(e, next);
            nextIndex++;
            expectedModCount++;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            Objects.requireNonNull(action);
            while (modCount == expectedModCount && nextIndex < size) {
                action.accept(next.item);
                lastReturned = next;
                next = next.next;
                nextIndex++;
            }
            checkForComodification();
        }

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
    //节点类,静态内部类,用来作为LinkedList内部的节点
    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;
        }
    }

    /**
     * 逆向迭代器,只能从后往前迭代
     * @since 1.6
     */
    public Iterator<E> descendingIterator() {
        return new DescendingIterator();
    }

    /**
     * Adapter to provide descending iterators via ListItr.previous
     */
    private class DescendingIterator implements Iterator<E> {
        private final ListItr itr = new ListItr(size());
        public boolean hasNext() {
            return itr.hasPrevious();
        }
        public E next() {
            return itr.previous();
        }
        public void remove() {
            itr.remove();
        }
    }

    @SuppressWarnings("unchecked")
    private LinkedList<E> superClone() {
        try {
            return (LinkedList<E>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }

    /**
     * 浅克隆方法
     */
    public Object clone() {
        LinkedList<E> clone = superClone();

        // Put clone into "virgin" state
        clone.first = clone.last = null;
        clone.size = 0;
        clone.modCount = 0;

        // Initialize clone with our elements
        for (Node<E> x = first; x != null; x = x.next)
            clone.add(x.item);

        return clone;
    }

    /**
     * 得到一个包含list所有元素的数组,长度为size
     */
    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;
    }

    /**
     * 将list中的元素存到为数组a中,如果a的长度不否就从新反射构建一个长度为size的数组,如果长度有多的,则就后面的都设置为null
     */
    @SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            a = (T[])java.lang.reflect.Array.newInstance(
                                a.getClass().getComponentType(), size);
        int i = 0;
        Object[] result = a;
        for (Node<E> x = first; x != null; x = x.next)
            result[i++] = x.item;

        if (a.length > size)
            a[size] = null;

        return a;
    }

    private static final long serialVersionUID = 876323262645176354L;

    /**
     * 将list实例保存到流中
     */
    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException {
        // Write out any hidden serialization magic
        s.defaultWriteObject();

        // Write out size
        s.writeInt(size);

        // Write out all elements in the proper order.
        for (Node<E> x = first; x != null; x = x.next)
            s.writeObject(x.item);
    }

    /**
     * 从流中读取list实例
     */
    @SuppressWarnings("unchecked")
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // Read in any hidden serialization magic
        s.defaultReadObject();

        // Read in size
        int size = s.readInt();

        // Read in all elements in the proper order.
        for (int i = 0; i < size; i++)
            linkLast((E)s.readObject());
    }

    /**
     * 用来多线程并行迭代的迭代器,这个迭代器的主要作用就是把list分成了好几段,每个线程执行一段,因此是线程安全的。
     */
    @Override
    public Spliterator<E> spliterator() {
        return new LLSpliterator<E>(this, -1, 0);
    }

    /** A customized variant of Spliterators.IteratorSpliterator */
    static final class LLSpliterator<E> implements Spliterator<E> {
        static final int BATCH_UNIT = 1 << 10;  // batch array size increment
        static final int MAX_BATCH = 1 << 25;  // max batch array size;
        final LinkedList<E> list; // null OK unless traversed
        Node<E> current;      // current node; null until initialized
        int est;              // size estimate; -1 until first needed
        int expectedModCount; // initialized when est set
        int batch;            // batch size for splits

        LLSpliterator(LinkedList<E> list, int est, int expectedModCount) {
            this.list = list;
            this.est = est;
            this.expectedModCount = expectedModCount;
        }

        final int getEst() {
            int s; // force initialization
            final LinkedList<E> lst;
            if ((s = est) < 0) {
                if ((lst = list) == null)
                    s = est = 0;
                else {
                    expectedModCount = lst.modCount;
                    current = lst.first;
                    s = est = lst.size;
                }
            }
            return s;
        }

        public long estimateSize() { return (long) getEst(); }

        public Spliterator<E> trySplit() {
            Node<E> p;
            int s = getEst();
            if (s > 1 && (p = current) != null) {
                int n = batch + BATCH_UNIT;
                if (n > s)
                    n = s;
                if (n > MAX_BATCH)
                    n = MAX_BATCH;
                Object[] a = new Object[n];
                int j = 0;
                do { a[j++] = p.item; } while ((p = p.next) != null && j < n);
                current = p;
                batch = j;
                est = s - j;
                return Spliterators.spliterator(a, 0, j, Spliterator.ORDERED);
            }
            return null;
        }

        public void forEachRemaining(Consumer<? super E> action) {
            Node<E> p; int n;
            if (action == null) throw new NullPointerException();
            if ((n = getEst()) > 0 && (p = current) != null) {
                current = null;
                est = 0;
                do {
                    E e = p.item;
                    p = p.next;
                    action.accept(e);
                } while (p != null && --n > 0);
            }
            if (list.modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

        public boolean tryAdvance(Consumer<? super E> action) {
            Node<E> p;
            if (action == null) throw new NullPointerException();
            if (getEst() > 0 && (p = current) != null) {
                --est;
                E e = p.item;
                current = p.next;
                action.accept(e);
                if (list.modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                return true;
            }
            return false;
        }

        public int characteristics() {
            return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
        }
    }

}

二、LinkedList源码分析

  1、继承关系:通过下面的代码可以看出LinkedList本身继承了AbstractSequentialList,说明LinkedList比较适合于顺序访问。同时它实现了Deque接口,说明LinkedList也是双端队列的一个实现。

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

  

  2、内部结构

    通过下面的代码可以看出LinkedList是基于node节点的双向链表,其内部定义了一个静态内部类Node来保存存入的数据,每次保存一个数据都会新建一个Node实例来进行存储。Node中item指向存入的数据,prev指向前一个节点,next指向后一个节点,如此节点之间连接起来构成一个双向链表,并不是循环链表。LinkedList类中定义了两个属性first和last分别用来指向第一个和最后一个节点,first和last要么都为null,要么都不为null。

  //节点类,静态内部类,用来作为LinkedList内部的节点
    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;
        }
    }

  /**
     * 指向第一节点
     * first和last要么都为null,要么都不为null。不要把节点node和节点的item混淆
     */
    transient Node<E> first;

    /**
     * 指向最后一个节点
     */
    transient Node<E> last;

  3、LinkedList与队列、双端队列和栈

  通过LinkedList 实现的接口Deque可知,LinkedList实现了队列和双端队列,同样栈的相关方法也表示在了接口Deque中。

    3.1、队列:有些队列是有长度的限制的,而LinkedList实现的队列没有长度限制

      add和offer 都是向队列尾部添加元素,但是add在容量不够的时候报错(LinkedList没有容量限制所以不会报错),而offer则会返回false。

      peek和element都是返回队列的第一个元素,如果没有元素peek返回null,element报错。但是二者在返回元素后不会将队列中的元素删除。

      poll和remove 都是返回队列中的第一个元素并且将该元素从队列中删除,如果没有元素poll返回null,remove则会报错。

        /**
     * 将元素添加到LinkedList尾部
     */
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

        /**
     * 新增一个元素到list尾部
     */
    public boolean offer(E e) {
        return add(e);
    }

        /**
     * 返回list第一个元素,没有元素不会报错
     */
    public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }

    /**
     * 返回list中第一个元素,list为空会报错
     */
    public E element() {
        return getFirst();
    }    

        /**
     * 返回并删除list中第一个元素,list为空不会报错
     */
    public E poll() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

    /**
     * 删除并返回第一个list中的元素,list为空会报错
     */
    public E remove() {
        return removeFirst();
    }

    3.2、双端队列:其实双端队列是在非双端队列的扩展,普通队列只能从尾部添加元素,从头部获取元素。双端队列是在两端都可以获取和添加元素。

  

  /**
     * 在队列的 最前端加入一个元素
     */
    public boolean offerFirst(E e) {
        addFirst(e);
        return true;
    }

    /**
     * 在队列的 最后端加入一个元素
     */
    public boolean offerLast(E e) {
        addLast(e);
        return true;
    }

    /**
     * 获取队列的第一个元素
     */
    public E peekFirst() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
     }

    /**
     * 获取队列的最后一个元素
     */
    public E peekLast() {
        final Node<E> l = last;
        return (l == null) ? null : l.item;
    }

    /**
     * 返回并删除队列中的第一个元素
     */
    public E pollFirst() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }

    /**
     * 返回并删除队列中的最后一个元素
     */
    public E pollLast() {
        final Node<E> l = last;
        return (l == null) ? null : unlinkLast(l);
    }

    3.3、栈

    栈只能是出栈和入栈,都是从头部添加和获取元素。

        /**
     * 返回list第一个元素,没有元素不会报错
     */
    public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }

        /**
     * 向栈中压入一个元素
     */
    public void push(E e) {
        addFirst(e);
    }

    /**
     * 从栈中弹出一个元素,栈为空会报错
     */
    public E pop() {
        return removeFirst();
    }    

三、LinkedList总结

  1、LinkedList是通过Node节点保存存入的元素,并通过prev和next指向前一个节点和后一个节点来实现双向链表。

  2、由于LinkedList是通过链表存储数据,所以查询某个下标的元素需要从头或者末尾开始查找,不能够随机快速访问,所以会慢一点。

  3、在新增数据都末尾的时候由于不需要进行扩容操作,所以比较快速。但是如果想要在某个下标处新增元素需要先遍历到该下标处获取节点后才能新增。

  4、由于实现了Deque,所以LinkedList也是队列、双端队列和栈的实现。

原文地址:https://www.cnblogs.com/kyleinjava/p/10815156.html

时间: 2024-10-12 04:38:27

java数据结构之LinkedList的相关文章

java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制)

转载请注明出处(请尊重原创!谢谢~): http://blog.csdn.net/javazejian/article/details/53073995 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) ??这篇是数据结构与算法的第3篇,通过前两篇的介绍,对应顺序表和链表已有

Java数据结构之链表的原理及LinkedList的部分源码剖析

一.为什么要学习数据结构? 做为一名程序员,不管你是用什么编程语言,数据结构是取底层的东西.就相当于盖楼的地基一样,地基做不好,上边再好也没有用. 在高级语言中,一般会对这些基础的数据结构进行封装,我们学要学习这些基础的东西吗? 当然是的,只有知道这些基础的东西,我们才能更好地使用语言封装好的api.举个最简单的例子,在Java中,List的实现类有ArrayList,LinkedList,Vector,你知道在什么情况下用哪个效率最高吗?只有知道其底层源才能更好地利用. 如何学习数据结构? 可

Java数据结构漫谈-LinkedList

同样是List的数据结构,LinkedList是使用了前后指针,指明节点的方式来表示链表的,这与之前介绍的ArrayList http://www.cnblogs.com/yakovchang/p/java_arraylist.html 中使用数组的方式是截然不同的.LinkedList中的存储节点被称作节点(Node),一个节点的定义如下所示: private static class Node<E> { E item; Node<E> next; Node<E> p

Java数据结构与算法之集合

线性表.链表.哈希表是常用的数据结构,在进行Java开发时,SDK已经为我们提供了一系列相应的类来实现基本的数据结构.这些类均在java.util包中. 一.Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object.一些Collection允许相同元素而另一些不行.一些能排序而另一些不行.Java  SDK不提供直接继承自Collection的类,Java  SDK提供的类都是继承自Collection的"子接口"如List和Set

java数据结构与算法之顺序表与链表深入分析

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/52953190 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 ??数据结构与算法这门学科虽然在大学期间就已学习过了,但是到现在确实也忘了不少,因此最近又重新看了本书-<数据结构与算法分析>加上之前看的<java数据结构>也算是对数据结构的进一步深入学习了,于是也就打算

java集合-LinkedList

LinkedList概念与简单实例 LinkedList类是双向列表,列表中的每个节点都包含了对前一个和后一个元素的引用. 1:LinkedList提供了4个不同位置的添加数据的方法,分别为链头插入,链尾插入,节点前插入,节点后插入 2:由于LinkedList是双向链表,在查询数据方面提供了"从前往后"和"从后往前"两个查询方法 3:如果数据量大,删除频繁,只能用LinkedList. 特别注意: list.get(i),LinkedList的底层是一个链表,随机

java数据结构与算法之平衡二叉树(AVL树)的设计与实现

[版权申明]未经博主同意,不允许转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/53892797 出自[zejian的博客] 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) java数据结构与算法之栈(Stack)设

java数据结构与算法之双链表设计与实现

转载请注明出处(万分感谢!): http://blog.csdn.net/javazejian/article/details/53047590 出自[zejian的博客] 关联文章: 关联文章: java数据结构与算法之顺序表与链表设计与实现分析 java数据结构与算法之双链表设计与实现 java数据结构与算法之改良顺序表与双链表类似ArrayList和LinkedList(带Iterator迭代器与fast-fail机制) ??上一篇文章分析顺序表和单链表,本篇就接着上篇继续聊链表,在单链表

Java ArrayList 和 LinkedList区别

ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 1.对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的.对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配:而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象. 2.在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动:而在LinkedList的中间插入或删除一