LinkedList从入门到入土

LinkedList从入门到入土

简介

​ 首先和数组同样,LinkedList也是一种线性数据结构,用链表实现的集合,元素有序且能够重复能够为nulljava

​ 因为其容许内存进行动态分配,意味着内存分配是由编译器在运行时完成的,咱们无需在LinkedList声明的时候指定大小node

​ 其也不须要在连续的位置上存储元素,由于节点能够经过引用指定下一个节点或者前一个节点,致使插入和删除的成本很低。git

​ LinkedList的实现是基于双向链表的,且头结点中不存放数据github

​ 和 ArrayList 同样,不是同步容器web

层级结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SAFdrM8w-1597210837179)(https://raw.githubusercontent.com/iszhonghu/Picture-bed/master/img/20200811170511.png)]数组

  • 也实现了Cloneable接口和Serializable接口,分别用来支持克隆以及序列化。数据结构

  • 其是一个继承自AbstractSequentiaList的双向链表,所以它也能够被当作堆栈、队列或双堆队列进行操做svg

  • 因为其实现了List接口,因此能对它进行队列操做函数

  • 因为实现了Deque接口,因此能将LinkedList当作双端队列使用this

关键结构

节点(Node)

​ LinkedList中的每个元素均可以称之为节点,每个节点都包含三个项目,其一就是元素自己,其二是执行像一个元素的引用地址,其三是指向上一个元素的引用地址

​ Node是LinkedList类的一个私有的静态内部类

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有两个构造函数,一个是默认的空的构造函数,一个是将已有元素的集合Collection的实例添加到LinkedList中,调用的是addAll方法。

增长方法

​ LinkedList有不少add方法,可是每次添加元素只是改变对应节点的上下指针引用,并且没有扩容,因此效率仍是很不错的

addFirst(E e)

​ 将指定元素添加到链表头

public void addFirst(E e) {
        linkFirst(e);
    }
 private void linkFirst(E e) {
        final Node<E> f = first;// 将头节点赋值给f
        final Node<E> newNode = new Node<>(null, e, f);//将指定元素构形成一个新节点,此节点的指向下一个节点的引用为头节点
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }
addLast(E e)和add(E e)

​ 和插入头节点差很少,逻辑层面基本同样

void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }
add(int index,E element)

​ 将指定的元素插入此列表中的指定位置

addAll(Collection<? extends E>c)

​ 按照指定集合的迭代器返回的顺序,将指定集合中的全部元素追加到此列表的末尾

删除方法

​ 删除元素和添加元素基本一致,就是改变对应元素指向上一节点和下一节点的引用便可。

remove和removeFirst

​ 从列表中移除第一个元素并返回该元素

removeLast

​ 从列表中删除最后一个元素并返回该元素

remove(int index)

​ 删除此列表中指定位置的元素

remove(Object o)

​ 若是存在,则从该列表中删除指定元素的第一次出现

修改元素set(int index Eelement)

​ 用指定的元素替换此列表中指定位置的元素,主要是经过node(index)方法获取指定索引位置的几点,而后修改此节点位置的元素

查找元素

getFirst()

返回此列表中第一个元素

getLast()

返回此列表中的最后一个元素

get(int index)

​ 返回指定索引处的元素

indexOf(Object o)

返回此列表中指定元素第一次出现的索引,若是此列表中不包含元素,则返回-1

遍历集合

​ 须要注意的是,modCount 字段,前面咱们在增长和删除元素的时候,都会进行自增操做 modCount,这是由于若是想一边迭代,一边用集合自带的方法进行删除或者新增操做,都会抛出异常。(使用迭代器的增删方法不会抛异常)

for循环

主要利用get(int index)方法

迭代器
Iterator<String> listIt = linkedList.listIterator();
 9 while(listIt.hasNext()){
10     System.out.print(listIt.next()+" ");
11 }
12 
13 //经过适配器模式实现的接口,做用是倒叙打印链表
14 Iterator<String> it = linkedList.descendingIterator();
15 while(it.hasNext()){
16     System.out.print(it.next()+" ");
17 }

​ 在其集合中也有一个内部类Listltr,

foreach循环

其底层使用的也是迭代器本质同样

迭代器和for循环效率差别

普通for循环:每遍历一个索引的元素以前,都要访问以前的全部索引

16 System.out.print(it.next()+" ");
17 }

​	在其集合中也有一个内部类Listltr,

##### foreach循环

其底层使用的也是迭代器本质同样

> 迭代器和for循环效率差别
>
> 普通for循环:每遍历一个索引的元素以前,都要访问以前的全部索引
>
> 迭代器:每次访问一个元素之后,都会用游标记录当前访问元素的位置,遍历一个元素,记录一个元素