容器-LinkedList指定位置添加元素的源码分析(九)

容器-LinkedList指定位置添加元素的源码分析(九)

  1. LinkedList指定索引位置添加元素

    • public static void main(String[] args) {
              
              
              List<String> list= new LinkedList<>();
              //添加元素
              list.add("a");
              list.add("b");
              list.add("c");
              list.add("a");
              list.add(5,"aaaa");//如果索引为5,则IndexOutOfBoundsException索引下标越界异常,因为现在的链表之有个元素,索引最多为3,如果你索引为4还是可以添加到索引为3后面的,但是索引5就不行了, 你跳过了4,就会出现索引下标越界异常。
      
  2. 用Ctrl+鼠标左键进入add源码,

    void add(int index, E element);
    
    • 在用Ctrl+Alt选择add方法的LinkedList接口实现类

       /**
           * Inserts the specified element at the specified position in this list.
           * Shifts the element currently at that position (if any) and any
           * subsequent elements to the right (adds one to their indices).
           *
           * @param index index at which the specified element is to be inserted
           * @param element element to be inserted
           * @throws IndexOutOfBoundsException {@inheritDoc}
           */
          public void add(int index, E element) {
              
              
              checkPositionIndex(index);//校验当前索引位置是否合法
      
              if (index == size)
                  linkLast(element);
              else
                  linkBefore(element, node(index));
          }
      
    • 然后我们看 checkPositionIndex(index);

          private void checkPositionIndex(int index) {
              
              
              if (!isPositionIndex(index))//isPositionIndex的方法是有返回值的,返回的是布尔类型
                  throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
              //如果isPositionIndex返回的是true,再取非,则不执行if条件语句
              //如果isPositionIndex返回的是false,再取非,则执行if条件语句,抛出异常
          }
      
      
    • 继续看isPositionIndex的方法实现

          /**
           * Tells if the argument is the index of a valid position for an
           * iterator or an add operation.
           */
          private boolean isPositionIndex(int index) {
              
              
              return index >= 0 && index <= size;
              //校验索引的合法性,就是索引大于等于0,还有索引小于等于元素的个数
          }
      
      
    • 我们返回去看最初的add方法,现在校验checkPositionIndex(index)已经合格,继续下面的语句

      public void add(int index, E element) {
              
              
              checkPositionIndex(index);//校验当前索引位置是否合法
      
              if (index == size)//如果索引等于元素的个数,则在元素的后面添加元素
                  linkLast(element);
              else//当索引小于元素的个数时,调用linkBefore()方法,把element穿进去了,通过node()方法,把index传进去了,node()方法是有返回值的,最终他要返回给linkBefore()方法取执行
                  linkBefore(element, node(index));
          }
      
    • 来看下node()的方法(重要理解)

       /**
           * Returns the (non-null) Node at the specified element index.
           */
          Node<E> node(int index) {
              
              // node是有返回值的,返回一个node的对象
              // 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;
              }
          }
      
      
    • node方法的具体分析

在这里插入图片描述

  • 然后我们回去看 linkBefore(element, node(index));

     /**
         * 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++;
        }
    
    
  • 分析 linkBefore方法的原理

在这里插入图片描述

  1. 所以说双向链表比数组增加删除元素效率高的原因,而为什么查询效率低呢,因为它要从头开始查到尾。

猜你喜欢

转载自blog.csdn.net/Xun_independent/article/details/114700151