java集合类库学习记录———LinkedList

1.介绍

LinkedList是List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括null)。

扩展了AbstractSequentialList抽象类,实现了Deque和Queue接口。这些操作允许将链接列表用作堆栈、队列和双端队列。

2.AbstractSequentialList

要实现一个列表,程序员只需要扩展此类,并提供 listIteratorsize 方法的实现即可。对于不可修改的列表,程序员只需要实现列表迭代器的hasNextnexthasPreviouspreviousindex 方法即可。

对于可修改的列表,程序员应该再另外实现列表迭代器的 set 方法。对于可变大小的列表,程序员应该再另外实现列表迭代器的 removeadd 方法。

AbstractSequentialList中的方法,add,addAll,remove,set,get方法和AbstractList一样都是基于迭代器实现的。但不同的是,在这个抽象类中没有实现自己的迭代器,由子类LinkedList自己实现。

3.Queue

除了基本的 Collection 操作外,队列还提供其他的插入、提取和检查操作。每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(nullfalse,具体取决于操作)。插入操作的后一种形式是用于专门为有容量限制的Queue 实现设计的;在大多数实现中,插入操作不会失败。

4.Deque

此接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(nullfalse,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的Deque 实现设计的;在大多数实现中,插入操作不能失败。

4.LinkedList

4.1 构造方法以及实现

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;
        }
    }

拥有2个构造器,1.空参构造器,创建了一个空的链表 2.用另一个集合初始化LinkedList。先创建了一个空链表,添加结合元素。

    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }
    public boolean addAll(Collection<? extends E> c) {
        return addAll(size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        checkPositionIndex(index);

        Object[] a = c.toArray();		//将集合中元素转化为数组
        int numNew = a.length;
        if (numNew == 0)
            return false;

        Node<E> pred, succ;
        if (index == size) {
            succ = null;			//处理要插入的整段元素的前向节点和后向节点
            pred = last;
        } else {
            succ = node(index);
            pred = succ.prev;
        }

        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;
        }

        if (succ == null) {			
            last = pred;
        } else {
            pred.next = succ;
            succ.prev = pred;
        }

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


4.2 基本工具方法

在LinkedList中有一些基本工具方法,LinkedFirst将元素链接在头部,linkLast将元素链接在尾部,linkBefore在指定节点前链接元素,unlinkFirst删除头节点元素,unlinkLast删除尾节点元素,unlink删除指定元素,node(index i)方法返回索引指向的节点

    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++;
    }

    /**
     * Links e as last element.
     */
    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++;
    }

    /**
     * Inserts element e before non-null Node succ.
     */
    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++;
    }

    /**
     * Unlinks non-null first node f.
     */
    private E unlinkFirst(Node<E> f) {			//当只有一个节点时,删除后first = last = null(不考虑0个节点是因为调用时就会先判断)
        // assert f == first && f != null;		//有一个节点以上时,删除后first = next,且头节点的前向链接为空
        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;
    }

    /**
     * Unlinks non-null last node l.
     */
    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;
    }

    /**
     * Unlinks non-null node x.
     */
    E unlink(Node<E> x) {	//判断前向元素和后向元素是否为空,前向元素为空则删除后向元素应为头节点,否则删除后prev.next = next;反之类似
        // 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;
    }
    Node<E> node(int index) {			//做了优化判断,当index<size/2时从前向搜索节点。否则从后向搜索节点
        // 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;
        }
    }


4.3实现了自己的ListIterator迭代器

    private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned;	//上一次跳过的节点
        private Node<E> next;		//下一次next时应跳过的节点
        private int nextIndex;		//下一次next时应跳过的节点的标号
        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++;
        }

此外还实现了一个反向迭代器

    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();
        }
    }





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: LinkedListJava集合类之一,是一个双向链表。它特有的方法包括: 1. addFirst(E e):将指定元素插入此列表的开头。 2. addLast(E e):将指定元素插入此列表的结尾。 3. getFirst():返回此列表的第一个元素。 4. getLast():返回此列表的最后一个元素。 5. removeFirst():移除并返回此列表的第一个元素。 6. removeLast():移除并返回此列表的最后一个元素。 7. offerFirst(E e):在此列表的开头插入指定的元素。 8. offerLast(E e):在此列表的结尾插入指定的元素。 9. pollFirst():获取并移除此列表的第一个元素,如果此列表为空,则返回 null。 10. pollLast():获取并移除此列表的最后一个元素,如果此列表为空,则返回 null。 ### 回答2: List是Java集合类中常用的一种,而LinkedList是List集合中的一种实现,和ArrayList相比,它具有一些独特的方法。 首先,LinkedList支持在list开头和结尾添加元素的方法。即addFirst(E e)和addLast(E e)。这两个方法在其他List实现中是没有的。这对于链表来说非常方便,因为在链表中,添加元素时只需要修改指针的指向即可,而不用像数组一样需要移动其他元素。 其次,LinkedList支持获取链表的头部和尾部元素的方法。即getFirst()和getLast()。同样,其他List实现中也没有这种方法,这也是LinkedList适合做队列和栈这种数据类型的原因之一。 除了这些独有的方法之外,LinkedList还具有一些其他List实现也有的方法。例如remove(int index)和size()方法就是常规List接口所具有的。LinkedList还实现了Queue和Deque接口,使得LinkedList也可以充当队列和双端队列。 需要注意的一点是,由于LinkedList是链表的形式,所以访问其中的元素时速度比较慢。因此,在需要随机访问元素的情况下,最好使用ArrayList。但是,当需要频繁在开头和结尾添加或删除元素时,LinkedList则具有明显的优势。 总之,LinkedList是List集合中的一种实现,它具有一些独特的方法,如addFirst,getFirst等方法。同时,它也可以作为队列、栈、双端队列等数据结构的实现。但是在需要随机访问元素的情况下,建议使用其他List实现,如ArrayList。 ### 回答3: Java集合类是Java编程中常用的工具之一,List是其中一种很重要的集合类。LinkedList是List的一种实现方式,LinkedList在插入和删除数据方面比较快。本文将会介绍LinkedList的特有方法的使用。 LinkedList继承了AbstractSequentialList,也实现了List、Deque、Cloneable、Serializable接口。由于LinkedList的底层实现是双向链表,因此它具有插入和删除元素效率高的特点。 下面是LinkedList特有的方法: 1. public void addFirst(E e),将指定元素添加到此列表的开头: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.addFirst("C++"); System.out.println(linkedList); // [C++, Java, Python] 2. public void addLast(E e),将指定元素添加到此列表的结尾: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.addLast("C++"); System.out.println(linkedList); // [Java, Python, C++] 3. public E removeFirst(),删除并返回此列表的第一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String first = linkedList.removeFirst(); System.out.println(first); // Java System.out.println(linkedList); // [Python, C++] 4. public E removeLast(),删除并返回此列表的最后一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String last = linkedList.removeLast(); System.out.println(last); // C++ System.out.println(linkedList); // [Java, Python] 5. public E getFirst(),返回此列表的第一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String first = linkedList.getFirst(); System.out.println(first); // Java 6. public E getLast(),返回此列表的最后一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String last = linkedList.getLast(); System.out.println(last); // C++ 7. public E peekFirst(),获取但不移除此列表的第一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String first = linkedList.peekFirst(); System.out.println(first); // Java System.out.println(linkedList); // [Java, Python, C++] 8. public E peekLast(),获取但不移除此列表的最后一个元素: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); linkedList.add("C++"); String last = linkedList.peekLast(); System.out.println(last); // C++ System.out.println(linkedList); // [Java, Python, C++] 9. public boolean offerFirst(E e),将指定元素插入此列表的开头: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); boolean result = linkedList.offerFirst("C++"); System.out.println(result); // true System.out.println(linkedList); // [C++, Java, Python] 10. public boolean offerLast(E e),将指定元素插入此列表的结尾: LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("Java"); linkedList.add("Python"); boolean result = linkedList.offerLast("C++"); System.out.println(result); // true System.out.println(linkedList); // [Java, Python, C++] LinkedList是一个非常实用的Java集合类,我们可以根据自己的需求选择使用其中的特有方法。在实际开发中,结合List可以方便地实现队列和栈的操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值