Java链式存储LinkedList----与ArrayList比较

简介: Java链式存储LinkedList----与ArrayList比较

作为一名对技术充满热情的学习者,我一直以来都深刻地体会到知识的广度和深度。在这个不断演变的数字时代,我远非专家,而是一位不断追求进步的旅行者。通过这篇博客,我想分享我在某个领域的学习经验,与大家共同探讨、共同成长。请大家以开放的心态阅读,相信你们也会在这段知识之旅中找到启示。



前言

同学们,今天我们一起来看看List接口的另一种实现LinkedList,看看如何实现对LinkedList链表的搭建.我们需要结合底层的逻辑,更深层次的熟悉链表数据结构.最后比较我们前面讲到的ArrayList动态数组实现,各自应用场景的不同.


一、LinkedList类:

在Java中,可以使用LinkedList类实现链表数据结构。链表是一种动态数据结构,与数组不同,链表的大小可以动态增长或缩小。

使用LinkedList实现链表

import java.util.LinkedList;
public class LinkedListExample {
    public static void main(String[] args) {
        // 创建一个LinkedList
        LinkedList<String> linkedList = new LinkedList<>();
        // 添加元素到链表
        linkedList.add("Java");
        linkedList.add("Python");
        linkedList.add("C++");
        // 打印链表中的元素
        System.out.println("Linked List: " + linkedList);
        // 在指定位置插入元素
        linkedList.add(1, "JavaScript");
        // 打印修改后的链表
        System.out.println("Updated Linked List: " + linkedList);
        // 获取链表中的元素
        String element = linkedList.get(2);
        System.out.println("Element at index 2: " + element);
        // 移除链表中的元素
        linkedList.remove("Python");
        // 打印最终的链表
        System.out.println("Final Linked List: " + linkedList);
    }
}

二、底层逻辑

LinkedList 是 Java 中的一个双向链表实现,实际上,它是一个由节点(Node)组成的链表结构。每个节点都包含了数据元素和对前一个节点和后一个节点的引用。

底层逻辑主要包括以下几个方面:

节点结构: LinkedList 中的节点是一个包含数据和两个引用的对象。每个节点有一个指向前一个节点的引用(prev),一个指向后一个节点的引用(next),以及节点的数据。

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 通过头指针(first)和尾指针(last)来标识链表的起始和结束。这些指针指向链表的第一个节点和最后一个节点。

transient Node<E> first;
transient Node<E> last;

添加元素: 在链表末尾或开头添加元素时,可以通过调整节点的引用来实现。添加到末尾时,修改last节点的next引用;添加到开头时,修改first节点的prev引用。

获取元素: 可以通过索引或迭代的方式获取链表中的元素。索引获取时,可以根据索引从头或尾开始遍历链表。

删除元素: 删除元素时,同样通过调整节点的引用来实现。如果删除的是中间节点,需要修改前一个节点的next引用和后一个节点的prev引用。

迭代器: LinkedList 提供了迭代器(ListIterator)来方便地遍历链表。

三.LinkedList与ArrayList的区别:

LinkedList 和 ArrayList 是 Java 中 List 接口的两个不同实现,它们在内部实现和性能特点上有一些区别。以下是它们之间的主要区别以及适用场景:

1.内部实现:

  • ArrayList 使用动态数组来存储元素,支持通过索引直接访问元素,因此对于随机访问和按索引查找性能较好。
  • LinkedList 使用双向链表来存储元素,对于插入和删除元素的操作较为高效,但对于随机访问性能较差。

2.随机访问性能:

  • ArrayList 对于随机访问非常高效,因为它可以通过索引直接访问数组元素,时间复杂度为 O(1)。
  • LinkedList 对于随机访问的性能相对较差,因为需要从链表的头部或尾部开始遍历,时间复杂度为 O(n),其中 n 是链表的长度。

3.插入和删除性能:

  • ArrayList 在中间插入或删除元素时,需要移动元素,因此效率较低,时间复杂度为 O(n)。
  • LinkedList 在插入和删除元素时,由于只需要调整相邻节点的引用,因此效率较高,时间复杂度为 O(1)。

4.空间复杂度:

  • ArrayList 的空间复杂度较小,因为它只需存储元素和数组的一些元信息。
  • LinkedList 的空间复杂度相对较大,因为每个节点都需要额外的空间存储两个引用。

5.适用场景:

  • 使用 ArrayList:
    1.当需要频繁进行随机访问和按索引查找时。
    2.数据集的大小是已知的或者相对固定的情况下。
  • 使用 LinkedList:
    1.当需要频繁进行插入和删除操作时,尤其是在中间位置。
    2.当数据集的大小可能动态变化,并且对内存占用不是主要关注点时。

代码示例:

ArrayList 示例:

import java.util.ArrayList;
public class ArrayList示例 {
    public static void main(String[] args) {
        // 创建一个 ArrayList
        ArrayList<String> arrayList = new ArrayList<>();
        // 向 ArrayList 中添加元素
        arrayList.add("Java");
        arrayList.add("Python");
        arrayList.add("C++");
        // 使用索引访问元素
        System.out.println("索引 1 处的元素: " + arrayList.get(1));
        // 遍历 ArrayList
        System.out.print("ArrayList 中的元素: ");
        for (String element : arrayList) {
            System.out.print(element + " ");
        }
        // 移除一个元素
        arrayList.remove("Python");
        // 移除后的最终 ArrayList
        System.out.print("\n移除后的 ArrayList: ");
        for (String element : arrayList) {
            System.out.print(element + " ");
        }
    }
}

LinkedList 示例:

import java.util.LinkedList;
public class LinkedList示例 {
    public static void main(String[] args) {
        // 创建一个 LinkedList
        LinkedList<String> linkedList = new LinkedList<>();
        // 向 LinkedList 中添加元素
        linkedList.add("Java");
        linkedList.add("Python");
        linkedList.add("C++");
        // 使用索引访问元素
        System.out.println("索引 1 处的元素: " + linkedList.get(1));
        // 遍历 LinkedList
        System.out.print("LinkedList 中的元素: ");
        for (String element : linkedList) {
            System.out.print(element + " ");
        }
        // 在开头添加一个元素
        linkedList.addFirst("JavaScript");
        // 添加后的最终 LinkedList
        System.out.print("\n添加后的 LinkedList: ");
        for (String element : linkedList) {
            System.out.print(element + " ");
        }
    }
}

总结

在学习List接口的两种不同的实现方式时,我们要尝试比较,在未来的应用时,选择合适的数据结构要取决于不同的应用场景.前提是大家对这两种结构的熟练程度是非常高的,希望大家可以对找点题目练练手,加深印象.

感谢大家阅读博主的文章,新人博主希望大家多多关注,我希望和大家一同进步,祝福大家在未来学习工作的路上一帆风顺,加油!!!

目录
相关文章
|
3月前
|
存储 Java API
深入剖析Java Map:不只是存储数据,更是设计艺术的体现!
【10月更文挑战第17天】在Java编程中,Map是一种重要的数据结构,用于存储键值对,并展现了设计艺术的精髓。本文深入剖析了Map的设计原理和使用技巧,包括基本概念、设计艺术(如哈希表与红黑树的空间时间权衡)、以及使用技巧(如选择合适的实现类、避免空指针异常等),帮助读者更好地理解和应用Map。
117 3
|
3月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
49 3
|
3月前
|
存储 Java
【编程基础知识】 分析学生成绩:用Java二维数组存储与输出
本文介绍如何使用Java二维数组存储和处理多个学生的各科成绩,包括成绩的输入、存储及格式化输出,适合初学者实践Java基础知识。
96 1
|
23天前
|
存储 Java
Java 11 的String是如何优化存储的?
本文介绍了Java中字符串存储优化的原理和实现。通过判断字符串是否全为拉丁字符,使用`byte`代替`char`存储,以节省空间。具体实现涉及`compress`和`toBytes`方法,前者用于尝试压缩字符串,后者则按常规方式存储。代码示例展示了如何根据配置决定使用哪种存储方式。
|
2月前
|
Java 索引 容器
Java ArrayList扩容的原理
Java 的 `ArrayList` 是基于数组实现的动态集合。初始时,`ArrayList` 底层创建一个空数组 `elementData`,并设置 `size` 为 0。当首次添加元素时,会调用 `grow` 方法将数组扩容至默认容量 10。之后每次添加元素时,如果当前数组已满,则会再次调用 `grow` 方法进行扩容。扩容规则为:首次扩容至 10,后续扩容至原数组长度的 1.5 倍或根据实际需求扩容。例如,当需要一次性添加 100 个元素时,会直接扩容至 110 而不是 15。
Java ArrayList扩容的原理
|
2月前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
121 2
|
2月前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
3月前
|
安全 Java 程序员
Java集合之战:ArrayList vs LinkedList,谁才是你的最佳选择?
本文介绍了 Java 中常用的两个集合类 ArrayList 和 LinkedList,分析了它们的底层实现、特点及适用场景。ArrayList 基于数组,适合频繁查询;LinkedList 基于链表,适合频繁增删。文章还讨论了如何实现线程安全,推荐使用 CopyOnWriteArrayList 来提升性能。希望帮助读者选择合适的数据结构,写出更高效的代码。
105 3
|
4月前
|
存储 Java
java数据结构,线性表链式存储(单链表)的实现
文章讲解了单链表的基本概念和Java实现,包括头指针、尾节点和节点结构。提供了实现代码,包括数据结构、接口定义和具体实现类。通过测试代码演示了单链表的基本操作,如添加、删除、更新和查找元素,并总结了操作的时间复杂度。
java数据结构,线性表链式存储(单链表)的实现
|
4月前
|
Java
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用
本文介绍了Java中抽象类和抽象方法的使用,以及ArrayList的基本操作,包括添加、获取、删除元素和判断列表是否为空。
38 2
java基础(12)抽象类以及抽象方法abstract以及ArrayList对象使用