Container-LinkedList source code analysis of adding elements at specified positions (9)

Container-LinkedList source code analysis of adding elements at specified positions (9)

  1. LinkedList specifies the index position to add an element

    • 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. Use Ctrl+left mouse button to enter the add source code,

    void add(int index, E element);
    
    • Use Ctrl+Alt to select the LinkedList interface implementation class of the add method

       /**
           * 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));
          }
      
    • Then we look at checkPositionIndex(index);

          private void checkPositionIndex(int index) {
              
              
              if (!isPositionIndex(index))//isPositionIndex的方法是有返回值的,返回的是布尔类型
                  throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
              //如果isPositionIndex返回的是true,再取非,则不执行if条件语句
              //如果isPositionIndex返回的是false,再取非,则执行if条件语句,抛出异常
          }
      
      
    • Continue to see the method implementation of 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,还有索引小于等于元素的个数
          }
      
      
    • Let's go back to see the original add method, now verify that checkPositionIndex(index) is qualified, continue with the following statement

      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));
          }
      
    • Take a look at the node() method (important understanding)

       /**
           * 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;
              }
          }
      
      
    • Specific analysis of node method

Insert picture description here

  • Then we go back to see 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++;
        }
    
    
  • Analyze the principle of the linkBefore method

Insert picture description here

  1. So the reason why the doubly linked list is more efficient than the array to add and delete elements, and why the query efficiency is low, because it needs to be searched from the beginning to the end.

Guess you like

Origin blog.csdn.net/Xun_independent/article/details/114700151