LinkedList从入门到入土

LinkedList从入门到入土

简介

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

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

​ 其也不需要在连续的位置上存储元素,因为节点可以通过引用指定下一个节点或者前一个节点,导致插入和删除的成本很低。

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

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

层级结构

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

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

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

  • 由于其实现了List接口,所以能对它进行队列操作

  • 由于实现了Deque接口,所以能将LinkedList当做双端队列使用

关键结构

节点(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循环:每遍历一个索引的元素之前,都要访问之前的所有索引
>
> 迭代器:每次访问一个元素以后,都会用游标记录当前访问元素的位置,遍历一个元素,记录一个元素

猜你喜欢

转载自blog.csdn.net/issunmingzhi/article/details/107955532
今日推荐