三十六、Collection - List

1、概述

java.util.List接口继承自Collection接口,是单列集合的一个重要分支,习惯性地会将实现了List接口的对象称为List集合。

List接口特点:

  1. 它是一个元素存取有序的集合。例如,存元素的顺序是 11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的。
  2. 它是一个带有索引的集合。 通过索引可以进行元素的操作。
  3. 集合中可以有重复的元素。通过元素的equals方法,来比较是否为重复的元素

2、List接口中常用的方法

List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:

方法 描述
public void add(int index, E element) 插入元素
public E get(int index) 根据索引获取元素
public E remove(int index) 根据索引删除元素
public E set(int index, E element) 根据索引删除元素

List集合特有的方法都是根据索引相关的。对集合操作,一般以索引优先。代码体现:

1624694188300

3、List - ArrayList集合

java.util.ArrayList集合数据存储的结构(数组结构)。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

许多程序员开发时非常随意地使用ArrayList完成任何需求,并不严谨,这种用法是不提倡的。

详细介绍

4、List - LinkedList集合

5.1 LinkedList概述

java.util.LinkedList集合数据存储的结构(链表结构)。方便元素添加、删除的集合。但不便于查询

LinkedList是一个双向链表,那么双向链表是什么样子的呢,我们用个图了解下

5.2 LinkedList集合方法

实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而 LinkedList 提供了大量首尾操作的方法

方法 描述
public void addFirst(E e) 将指定元素插入此列表的开头。
public void addLast(E e) 将指定元素添加到此列表的结尾。
public E getFirst() 返回此列表的第一个元素。
public E getLast() 返回此列表的最后一个元素。
public E removeFirst() 移除并返回此列表的第一个元素。
public E removeLast() 移除并返回此列表的最后一个元素。

LinkedList是List的子类,List中的方法LinkedList都是可以使用。在开发时,LinkedList集合也可以作为堆栈,队列的结构使用。

5.3 LinkList源码分析

  • LinkedList的成员变量源码分析:

    public class LinkedList<E> extends AbstractSequentialList<E>
        				implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
        transient int size = 0;
        /**
         *存储第一个节点的引用
         */
        transient Node<E> first;
    
        /**
         * 存储最后一个节点的引用
         */
        transient Node<E> last;
        
        //......
        //......
    }
    
  • LinkedList的内部类Node类源码分析:

    public class LinkedList<E> extends AbstractSequentialList<E>
        				implements List<E>, Deque<E>, Cloneable, java.io.Serializable{
        //......
        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;
            }
        }
        //......
    }
    
  • LinkedList的add()方法源码分析:

    public boolean add(E e) {
    	linkLast(e);//调用linkLast()方法
    	return true;//永远返回true
    }
    void linkLast(E e) {
      final Node<E> l = last;//一个临时变量,存储最后一个节点
      final Node<E> newNode = new Node<>(l, e, null);//创建一个Node对象
      last = newNode;//将新Node对象存储到last
      if (l == null)//如果没有最后一个元素,说明当前是第一个节点
     	first = newNode;//将新节点存为第一个节点
      else
     	l.next = newNode;//否则不是第一个节点,就赋值到当前的last的next成员
      size++;//总数量 + 1
      modCount++;//
    }
    
  • LinkedList的get()方法:

    public E get(int index) {
        checkElementIndex(index);		//检查索引的合法性(必须在0-size之间),如果不合法,此方法抛出异常
        return node(index).item;
    }
    Node<E> node(int index) {				//此方法接收一个索引,返回一个Node
        // assert isElementIndex(index);
        if (index < (size >> 1)) {			//判断要查找的index是否小于size / 2,二分法查找
            Node<E> x = first;				// x = 第一个节点——从前往后找
            for (int i = 0; i < index; i++)		//从0开始,条件:i < index,此循环只控制次数
                x = x.next;					//每次 x = 当前节点.next;
            return x;				//循环完毕,x就是index索引的节点。
        } else {
            Node<E> x = last;		// x = 最后一个节点——从后往前找
            for (int i = size - 1; i > index; i--)	//从最后位置开始,条件:i > index
                x = x.prev;			//每次 x = 当前节点.prev;
            return x;				//循环完毕,x就是index索引的节点
        }
    }
    
posted @ 2021-06-27 16:06  火烧云Z  阅读(57)  评论(0)    收藏  举报