java.util.LinkedList 类

本文详细介绍了Java中的LinkedList类,作为List集合的一种实现,它由链表结构构成,克服了数组的一些缺点。LinkedList支持动态内存管理,但牺牲了随机访问的效率。文章详细讲解了LinkedList的构造、字段属性、添加、删除、修改、查找元素的操作,以及遍历集合的两种方式(普通for循环和迭代器)。对比了迭代器和for循环在效率上的差异,强调在大量元素遍历时,迭代器的优势更为明显。
摘要由CSDN通过智能技术生成

1 引言

​ 前面我们介绍了List集合的一种典型实现 ArrayList,我们知道 ArrayList 是由数组构成的,这次我们介绍 List 集合的另一种典型实现 LinkedList,这是一个由链表构成的数组。

​ 大家都知道数组作为数据存储结构有一定的缺陷。在无序数组中,搜索性能差,在有序数组中,插入效率又很低,而且这两种数组的删除效率都很低,并且数组在创建后,其大小是固定了,设置的过大会造成内存的浪费,过小又不能满足数据量的存储。

​ 我们知道数组是一种通用的数据结构,能用来实现栈、队列等很多数据结构。而链表也是一种使用广泛的通用数据结构,它也可以用来作为实现栈、队列等数据结构的基础,基本上除非需要频繁的通过下标来随机访问各个数据,否则很多使用数组的地方都可以用链表来代替。

​ 但是我们需要说明的是,链表是不能解决数据存储的所有问题的,它也有它的优点和缺点。

2 链表

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

​ 链表有很多种,分别是单向链表、双端链表、有序链表、双向链表以及有迭代器的链表。 每个链表都包括一个LinikedList对象和许多Node对象,LinkedList对象通常包含头和尾节点的引用,分别指向链表的第一个节点和最后一个节点。而每个节点对象通常包含数据部分data,以及对上一个节点的引用prev和下一个节点的引用next,只有下一个节点的引用称为单向链表,两个都有的称为双向链表。next值为null则说明是链表的结尾,如果想找到某个节点,我们必须从第一个节点开始遍历,不断通过next找到下一个节点,直到找到所需要的。栈和队列都是ADT(数据抽象类型:一个数学模型及定义在该模型上的一组操作),可以用数组来实现,也可以用链表实现。

3 LinkedList定义

LinkedList 是一个用链表实现的集合,元素有序且可以重复。

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

在这里插入图片描述

​ 和 ArrayList 集合一样,LinkedList 集合也实现了Cloneable接口和Serializable接口,分别用来支持克隆以及支持序列化。List 接口也不用多说,定义了一套 List 集合类型的方法规范。

注意,相对于 ArrayList 集合,LinkedList 集合多实现了一个 Deque 接口,这是一个双向队列接口,双向队列就是两端都可以进行增加和删除操作

4 字段属性

    //链表元素(节点)的个数
    transient int size = 0;

    /**
     *指向第一个节点的指针
     */
    transient Node<E> first;

    /**
     *指向最后一个节点的指针
     */
    transient Node<E> last;

注意这里出现了一个 Node 类,这是 LinkedList 类中的一个内部类,其中每一个元素就代表一个 Node 类对象,LinkedList 集合就是由许多个 Node 对象类似于手拉着手构成

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 是有四个元素,也就是由 4 个 Node 对象组成,size=4,head 指向第一个elementA,tail指向最后一个节点elementD

5 构造函数

 public LinkedList() {
   
    }
  public LinkedList(Collection<? extends E> c) {
   
    this();
    addAll(c);
}

​ LinkedList 有两个构造函数,第一个是默认的空的构造函数,第二个是将已有元素的集合Collection 的实例添加到 LinkedList 中,调用的是 addAll() 方法,这个方法下面我们会介绍。

注意:LinkedList 是没有初始化链表大小的构造函数,因为链表不像数组,一个定义好的数组是必须要有确定的大小,然后去分配内存空间,而链表不一样,它没有确定的大小,通过指针的移动来指向下一个内存地址的分配。

6 添加元素

6.1 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;//将新节点设为头节点,那么原先的头节点 f 变为第二个节点
        if (f =
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值