首页 > 编程语言 >深入解析 Java LinkedList:从基本特点到常用方法的全面介绍

深入解析 Java LinkedList:从基本特点到常用方法的全面介绍

时间:2024-11-25 09:31:36浏览次数:11  
标签:index Java LinkedList 删除 元素 list 链表 解析

LinkedList 是 Java 集合框架中非常常用的一种实现类,主要用于存储有序元素的链式结构。与 ArrayList 这种基于数组的实现不同,LinkedList 使用双向链表来管理数据。在本文中,我们将从 LinkedList 的基本特点、继承关系、扩容机制、常用方法源码介绍、增删改查等多个方面详细解读 LinkedList 的工作原理,帮助大家全面理解这一常用的数据结构。

1. LinkedList 的基本特点

LinkedList 是 Java 中 List 接口的一种实现类,底层是基于双向链表(Doubly Linked List)实现的。与 ArrayList 的固定大小数组不同,LinkedList 通过节点(Node)将元素串联起来,节点之间通过指针相互链接。具体特点如下:

  • 双向链表LinkedList 是基于双向链表实现的,每个节点包含指向前一个节点和后一个节点的引用,使得在双向链表中插入和删除元素的操作非常高效。
  • 无序存储:与 ArrayList 不同,LinkedList 不保证元素的存储顺序,因此,它在内存中的存储是离散的,每个元素都有一个指向前后元素的引用。
  • 内存消耗:由于每个节点需要额外的内存来存储前后指针,因此,LinkedList 的内存开销要大于 ArrayList
  • 插入和删除效率LinkedList 在插入和删除元素时(尤其是在中间位置)非常高效,时间复杂度为 O(1),但访问元素的时间复杂度为 O(n),不如 ArrayList 快。
  • 线程不安全:与其他集合类一样,LinkedList 并不是线程安全的。

示例:

LinkedList<String> list = new LinkedList<>();
list.add("Java");
list.add("C++");
list.add("Python");
System.out.println(list);  // 输出: [Java, C++, Python]

2. LinkedList 的继承关系

LinkedList 继承自 AbstractSequentialList 并实现了 ListDeque 接口。具体的继承关系如下:

Object
  |
AbstractCollection
  |
AbstractSequentialList
  |
LinkedList
  • AbstractCollection:提供了 Collection 接口的默认实现。
  • AbstractSequentialList:提供了基于链表的 List 接口实现,它主要通过继承 AbstractList,并通过链表特性优化 get(int index)set(int index, E element) 方法。
  • LinkedList:实现了 List 接口,提供了链表结构的各种操作(例如插入、删除、获取元素等)。

3. 增加元素 + 扩容机制

LinkedListArrayList 不同,LinkedList 不需要进行扩容,因为它是通过链表实现的,元素是动态链接的。因此,链表结构本身是灵活的,可以在任意位置插入或删除元素。

增加元素:

LinkedList 中,可以使用 add() 方法向链表尾部添加元素,也可以使用 addFirst()addLast() 分别将元素添加到链表的头部和尾部。

LinkedList<String> list = new LinkedList<>();
list.add("Java");
list.addFirst("C++");
list.addLast("Python");
System.out.println(list);  // 输出: [C++, Java, Python]

插入元素:

可以使用 add(index, element) 方法在指定位置插入元素。如果指定的索引无效,则抛出 IndexOutOfBoundsException

list.add(1, "Ruby");
System.out.println(list);  // 输出: [C++, Ruby, Java, Python]

4. 常用的方法源码介绍

add() 方法

add() 方法用于在链表的尾部添加元素。它在实现中会创建一个新的节点并将其连接到链表的末尾。

public boolean add(E e) {
    linkLast(e);
    return true;
}

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++;
}

remove() 方法

remove() 方法用于删除链表中的元素。如果删除的是指定元素,则需要遍历链表来找到该元素并进行删除。

public E remove() {
    if (size == 0)
        throw new NoSuchElementException();
    return unlinkFirst(first);
}

E unlinkFirst(Node<E> f) {
    final E element = f.item;
    final Node<E> next = f.next;
    f.item = null;
    f.next = null;
    first = next;
    if (next == null)
        last = null;
    else
        next.prev = null;
    size--;
    modCount++;
    return element;
}

get() 方法

get() 方法用于获取指定位置的元素。由于 LinkedList 是基于链表的,获取元素的时间复杂度为 O(n)

public E get(int index) {
    checkElementIndex(index);
    return node(index).item;
}

Node<E> node(int index) {
    if (index < (size >> 1)) {
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}

5. 删除元素

删除元素时,LinkedList 提供了几种常用方法:

  • remove():移除并返回链表头部的元素。
  • removeLast():移除并返回链表尾部的元素。
  • remove(int index):移除指定索引位置的元素。

删除元素:

list.remove(1);  // 删除索引为1的元素
System.out.println(list);  // 输出: [C++, Java]

6. 改动元素

改动元素通常使用 set() 方法,它会替换链表中指定位置的元素。

list.set(1, "JavaScript");
System.out.println(list);  // 输出: [C++, JavaScript]

7. 查询元素

LinkedList 中,常用的查询方法包括 get()indexOf()contains()

  • get():根据索引获取元素。
  • contains():检查链表中是否包含指定元素。
  • indexOf():查找元素第一次出现的位置。

查询元素:

boolean contains = list.contains("Java");
System.out.println(contains);  // 输出: true

int index = list.indexOf("JavaScript");
System.out.println(index);  // 输出: 1

8. 最后总结

总结:

LinkedList 是基于双向链表实现的集合类,具有以下优点:

  • 插入和删除效率高:在链表的头部和尾部进行插入和删除操作非常高效,时间复杂度为 O(1)
  • 内存开销大:每个节点需要额外的空间存储前向和后向的引用,因此 LinkedList 的内存开销相对较大。
  • 查询效率低:由于 LinkedList 是线性结构,因此查询元素的时间复杂度为 O(n),效率较低。

使用建议:

  • LinkedList 适合用于频繁插入和删除操作的场景,特别是当插入和删除发生在链表的头部或尾部时。
  • 如果需要频繁随机访问元素,则应该选择 ArrayList,因为它的查询速度更快,且内存开销较小。

LinkedList 提供了灵活的链表操作方式,可以帮助我们在适当的场景下选择合适的集合类。

标签:index,Java,LinkedList,删除,元素,list,链表,解析
From: https://blog.csdn.net/fulai00/article/details/143861081

相关文章

  • Java项目实战II基于SPringBoot的玩具销售商城管理系统(开发文档+数据库+源码)
    目录一、前言二、技术介绍三、系统实现四、核心代码五、源码获取全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末一、前言随着儿童娱乐与教育需求的日益增长,玩具市场呈现出蓬勃......
  • C++20中的Concepts 与 Java/C#中的范型约束
    C++20中的Concepts与Java/C#中的范型约束大家好!最近对C++20中的Concepts非常上头,上一篇聊了C++20中的Concepts与TypeScript,那么今天,就索性连Java和C#中的相似特性一起聊了算了。C++20引入了概念(Concepts),它是一种用来对模板参数进行约束的机制,能够提升模板编程的类型安......
  • Java基于微信小程序的校园跑腿平台(V2.0)
    博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w+、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌......
  • 【分享】这篇教程助力你成为 JavaScript 糕手!(十一)
    第十一章:异步编程11.1异步编程的概念在JavaScript中,异步编程是一种非常重要的编程模式,它用于处理那些不会立即完成的操作,而是在一段时间后才会返回结果的任务。传统的同步编程模式下,代码是按照从上到下的顺序依次执行的,每一行代码都必须等待前一行代码执行完毕后才会......
  • Java2024-高频面试题(附答案)
    *1、SpringCloud有哪些常用组件?分别是什么作用?答:Nacos,OpenFeign,Sentinel,Seata,RabbitMQ,GatewayNacos:服务注册中心,提供服务注册和发现功能OpenFeign:实现远程调用Sentinel:提供服务容错保护Seata:实现分布式事务管理RabbitMQ:实现异步通知Gateway:(API网关......
  • Java学习笔记——2024.11.24
    2024.11.24一、快速入门1.小需求//Hello.javapublicclassHello{publicstaticvoidmain(String[]args){System.out.println("hello,world~");}}=>javacHello.java//如果有中文注释要保证java文件的编码正确(控制台只认gbk)=>javaHell......
  • 前端必知必会-JavaScript 按位运算
    文章目录JavaScript按位运算JavaScript使用32位按位操作数JavaScript按位与JavaScript按位或JavaScript按位异或JavaScript按位与(&)JavaScript按位或(|)JavaScript按位异或(^)JavaScript按位非(~)JavaScript(零填充)按位左移(<<)JavaScript(零填充)右移......
  • 前端必知必会-JavaScript 运算符优先级
    文章目录JavaScript运算符优先级运算符优先级值增量运算符算术运算符移位运算符关系运算符比较运算符按位运算符逻辑运算符条件(三元)运算符赋值运算符总结JavaScript运算符优先级运算符优先级描述算术表达式中执行运算的顺序。乘法(*)和除法(/)的优先级高于......
  • 【Mybatis与Spring整合】Java项目中占位符与大小写匹配规范的重要性
    在开发Java项目时,细节决定成败。一次不经意的占位符书写错误或大小写不匹配可能导致项目运行失败。本文基于实际问题,总结了占位符配置规范和解决办法,希望为大家提供参考。一、Spring占位符配置问题在Spring项目中,<context:property-placeholder>标签用于加载外部配置文件并......
  • [20241123]测试软软解析遇到的疑惑3.txt
    [20241123]测试软软解析遇到的疑惑3.txt--//测试软软解析遇到的疑惑,就是大量软软解析以及分散执行两者的执行时间差别并不是很大,有点疑惑,发现调用select休眠的时间--//是1毫秒,而11g是1厘秒。而ash取样是1秒,这样在21c下相当于方法1000倍,11g下仅仅100倍。--//前面测试21c下的情况,在1......