LinkedList集合

版权声明:chaizepeng https://blog.csdn.net/chaizepeng/article/details/81154196

1、特点

LinkedList集合实现了List接口,底层数据结构是一个双向链表,查询慢,增删快,线程不安全,效率高。

2、功能及源码

1)内部类

链表节点类

 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)成员变量

     transient int size = 0;

     transient Node<E> first;//头节点

     transient Node<E> last;//尾节点

3)构造方法

    public LinkedList() {
    }

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

    //将c添加到链表的尾部

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

    public boolean addAll(int index, Collection<? extends E> c) {//index = size
        //检查传入的集合大小是否合理
        checkPositionIndex(index);
        Object[] a = c.toArray();//集合转成数组
         int numNew = a.length;//获取数组长度
         if (numNew == 0)//如果长度是0,没有元素,直接返回
                 return false;
         Node<E> pred, succ;//声明两个结点,前驱结点pred 、 后继结点succ
         if (index == size) {//这里true,index表示在哪里开始添加,如果添加下标和链表大小相同,则就是在末尾添加
                  succ = null;//后继节点为空
                  pred = last;//前驱节点指向链表中的最后一个结点
          } else {
                  succ = node(index);//获取到index位置的结点,succ指向此节点,也就是新建结点的后继结点指向index位置的结点
                  pred = succ.prev;//新建结点的前驱结点指向index位置结点的原来的前一个结点结点
          }

           for (Object o : a) {
                    @SuppressWarnings("unchecked") E e = (E) o;
                   Node<E> newNode = new Node<>(pred, e, null);//利用上面的前驱和后继结点创建一个结点,添加到链表
                   if (pred == null)//前驱结点是null,链表中没结点
                           first = newNode;//则初始化头节点
                   else
                   pred.next = newNode;//让pred的后继结点指向新添加的节点,也就是index位置原先的前一个结点的后继结点指向新节点,大白话就是在index位置和index-1位置直接新添加一个结点
                    pred = newNode;//然后让pred节点指向新添加的节点
             }
            if (succ == null) {//如果后继结点是空,初始化尾节点
                    last = pred;
             } else {
                    pred.next = succ;//pred的下一个节点指向succ
                    succ.prev = pred;//succ的上一个节点指向pred
              }
             size += numNew;//链表中元素个数
             modCount++;//链表改变标记+1
             return true;
      }


//获取到index处的结点
Node<E> node(int index) {
      if (index < (size >> 1)) {//如果结点所在的位置在链表的前半段,则从前往后遍历
      //一直将指针指到index处,获取到结点
              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)添加单个元素方法

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

添加结点时,只需要创建一个结点,然后链起来即可,所以增删效率高。

5)获取元素的方法

//获取到index处的结点
Node<E> node(int index) {
      if (index < (size >> 1)) {//如果结点所在的位置在链表的前半段,则从前往后遍历
      //一直将指针指到index处,获取到结点
              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;
       }
  }

获取元素时,需要挨个遍历,所以查询效率低。

3、遍历LinkedList

1)for循环

        LinkedList<String> list = new LinkedList<>();
        list.add("1111");
        list.add("2222");
        list.add("3333");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

2)迭代器

        LinkedList<String> list = new LinkedList<>();
        list.add("1111");
        list.add("2222");
        list.add("3333");
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()) {
            System.out.println(iterator.next());
        }

3)增强for

        LinkedList<String> list = new LinkedList<>();
        list.add("1111");
        list.add("2222");
        list.add("3333");
        for (String string : list) {
            System.out.println(string);
        }

猜你喜欢

转载自blog.csdn.net/chaizepeng/article/details/81154196