1、LinkedList适合场景:适合数据频繁添加删除操作,写多读少的场景
2、LinkedList的数据结构—双向链表(链表由若干个Node对象组成)
双向链表整体结构如下图所示:
first:头结点,它的前一个元素为空
last:尾结点,它的后一个元素为空
Node:链表的每个结点,Node的源码如下:
Node的属性:item代表数据域,next代表后一个结点的位置,prev代表前一个结点的位置
3、通过LinkedList源码分析常用的方法
3.1、添加元素
boolean add(E e):添加元素至尾部。在链表的末尾添加一个元素,并返回一个布尔值表示添加是否成功。将要添加的元素传给linkLast()方法,并调用这个方法。
首先,将最后一个结点的引用保存在l中,然后创建一个新结点newNode,将其前驱结点设置为l,后继结点设置为null,值为传进来的元素,将链表的last指向新结点newNode。判断最后一个结点是否为空,如果是,则说明链表为空,将first指向新结点newNode;否则,将最后一个结点的next指向新结点newNode。
3.2、void addFirst(E e):添加新元素至链表头部(LinkedList特有的方法)
在addFirst()方法内调用linkFirst()方法,将传入的元素作为参数传入。
将当前链表的头部结点保存在声明的变量里,然后创建一个名为 newNode 的新结点,将其前驱结点指向 null,后继结点指向 f,值为传入的参数 e。将链表的头部结点 first 指向新结点 newNode。如果原来的头部结点 f 为空,则说明链表原本是空的,因此将尾部结点 last 也指向新结点。否则,将原来的头部结点 f 的prev指向新结点。
3.3、void addLast(E e):添加新元素值链表尾部(LinkedList特有的方法)
其基本思想与addFirst()方法相似,这里是将链表的最后一个结点赋值给l,然后创建一个新节点,将其前驱结点指向l,元素值为e,后继结点为null。将链表的最后一个结点last指向新结点newNode。
3.4、E get():遍历链表,查找指定位置的元素
将索引传给get()方法,先调用checkElementIndex()方法,然后调用node()方法来获取指定位置的节点,并返回该节点的元素。
调用checkElementIndex()方法来检查下标是否越界,如果下标越界,则会抛出异常。
先判断index是否小于size >> 1(链表长度的一半),如果是,从链表头结点开始遍历结点,直到找到指定位置的结点并返回该结点。如果index大于等于链表长度的一半,则从链表尾结点开始遍历结点,直到找到指定位置的结点并返回该结点。
3.5、E getFirst():获取链表的头元素(LinkedList特有的方法);E getLast():获取链表的尾元素(LinkedList特有的方法)
将链表中的第一个结点赋给f,再判断f是否为空,如果为空则抛出异常,否则返回f结点的元素值。
将链表中的最后一个结点赋给l,再判断l是否为空,如果为空则抛出异常,否则返回l结点的元素值。
3.6、int indexOf():查找链表中的指定元素的下标位置,如果不存在,则返回-1
定义一个index变量表示出现的次数。如果传入的下标为null,遍历链表并判断链表中是否也有结点值为null,若有,则返回当前的下标。如果不是null,则遍历链表并判断链表中是否也有结点值为o的参数,若有,则返回当前的下标。如果在遍历完整个链表后都没有找到符合条件的结点,则返回-1。
3.7、链表中删除元素的方法有多个,这里只讲其中的一种方法
(1)remove():删除链表中的头元素
(2)boolean remove():删除指定内容的元素
(3)remove(int index):删除指定位置的元素
(4)removeFirst():删除头元素
(5)removeLast():删除尾元素
调用了remove()方法中的removeFirst()方法。
将链表的头结点赋给f。如果链表为空,抛出NoSuchElementException()异常。如果链表不为空,调用unlinkFirst(f)方法删除头结点并返回被删除元素的值。
先保存结点的值和下一个结点的引用,将结点的值和下一个结点的引用设置为null,将链表的头指向下一个结点。如果下一个结点为null,则链表为空,将尾结点指向null。否则,将下一个结点的前驱指向null。然后让链表的长度减小,返回删除结点的值。
3.8、default void sort(Comparator c):按照Comparator比较器,将链表中的所有元素进行排序
sort()方法接受一个类型为Comparator比较器的参数,用于定义元素之间的顺序。先将列表转换为一个Object类型的数组,使用Arrays.sort方法对该数组进行排序,排序时传入了一个比较器,然后获取列表的迭代器,并通过for循环遍历数组,并将数组中的元素设置为列表中的元素。
3.9、Object[] toArray():将链表转换成数组(没有参数)
先创建一个长度为链表大小的数组,通过遍历链表中的每一个结点,把结点的值添加到数组中。
3.10、T[] toArray(T[] a):将链表转换成数组(参数为数组)
该方法接受一个类型为T的数组作为参数,并将链表中的元素复制到该数组中。如果传入的数组长度小于链表的大小,则会使用反射来创建一个新的长度为链表大小的数组。如果传入的数组长度大于链表的大小,则会将最后一个元素设为null。