三十六、Collection - List
1、概述
java.util.List
接口继承自Collection
接口,是单列集合的一个重要分支,习惯性地会将实现了List
接口的对象称为List集合。
List接口特点:
- 它是一个元素存取有序的集合。例如,存元素的顺序是 11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的。
- 它是一个带有索引的集合。 通过索引可以进行元素的操作。
- 集合中可以有重复的元素。通过元素的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集合特有的方法都是根据索引相关的。对集合操作,一般以索引优先。代码体现:
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索引的节点 } }