0
点赞
收藏
分享

微信扫一扫

Java(day113):LinkedList:Java中高效的双向链表实现!

前言

  在Java集合框架中,LinkedList是一个非常重要且常用的类,它实现了ListQueue接口。作为一个链表结构的实现,LinkedList能够在一些特定的应用场景中提供比ArrayList更高效的操作,尤其是在插入和删除元素时。那么,LinkedList是如何工作的?它又适用于哪些场景呢?今天我们就来深入了解一下LinkedList

什么是LinkedList?

  LinkedList是Java集合框架中的一个实现类,它使用双向链表(Double Linked List)来存储元素。与ArrayList不同,LinkedList并不使用连续的内存块来存储数据,而是通过链表节点(Node)将元素链接在一起。

  每个节点包含一个数据元素和两个指针:一个指向下一个节点,另一个指向前一个节点。通过这种方式,LinkedList能够非常高效地在列表的两端进行插入和删除操作,而不像ArrayList那样需要移动数组中的元素。

  具体来说,LinkedList由以下几个主要部分组成:

  1. 节点(Node):每个节点存储一个元素以及指向前后节点的指针(prev指针和next指针)。
  2. 头节点(Head):链表的起始节点,指向链表的第一个元素。
  3. 尾节点(Tail):链表的最后一个节点,指向链表的末尾。

LinkedList的特点

  1. 双向链表LinkedList是基于双向链表实现的,每个元素不仅指向下一个元素,还指向上一个元素。因此,LinkedList支持从任意一端进行操作,既适合用于顺序访问,也适合用于反向访问

  2. 动态大小:与ArrayList不同,LinkedList不需要预定义大小。它是动态的,能够根据需要自动增长或缩小。每个节点都是独立分配的内存块,因此元素的插入和删除不需要移动其他元素。

  3. 高效的插入与删除操作LinkedList在插入和删除元素时非常高效,尤其是在链表的头部和尾部。插入和删除元素的时间复杂度为O(1),但是在链表中间插入或删除元素时需要遍历链表,时间复杂度为O(n)

  4. 较慢的随机访问:由于LinkedList需要通过遍历链表来访问元素,它在访问元素时的效率相对较低。与ArrayList相比,LinkedList的访问操作(get()set())的时间复杂度为O(n),而ArrayList的时间复杂度为O(1)

  5. 内存开销较大:每个LinkedList节点需要存储两个额外的指针(指向前一个节点和下一个节点),因此LinkedList的内存开销比ArrayList更高。

LinkedList的常用方法

LinkedList继承自AbstractSequentialList并实现了ListQueue接口,因此它包含了许多常见的List方法,还提供了Queue接口的方法。以下是一些常用方法:

  • add(E e):将指定的元素添加到列表的尾部。
  • addFirst(E e):将指定的元素添加到列表的头部。
  • addLast(E e):将指定的元素添加到列表的尾部。
  • remove(Object o):从列表中删除指定的元素。
  • removeFirst():删除并返回列表中的第一个元素。
  • removeLast():删除并返回列表中的最后一个元素。
  • get(int index):返回指定位置的元素。
  • set(int index, E element):替换指定位置的元素。
  • contains(Object o):检查列表中是否包含指定的元素。
  • size():返回LinkedList中的元素个数。
  • isEmpty():判断LinkedList是否为空。
  • clear():清空LinkedList中的所有元素。
  • peekFirst():获取并返回第一个元素,但不删除它。
  • peekLast():获取并返回最后一个元素,但不删除它。

LinkedList的使用示例

下面是一个简单的代码示例,展示如何使用LinkedList进行基本操作:

代码示例:
import java.util.LinkedList;

public class LinkedListExample {
    public static void main(String[] args) {
        // 创建一个LinkedList实例
        LinkedList<String> list = new LinkedList<>();
        
        // 添加元素
        list.add("Java");
        list.add("Python");
        list.add("JavaScript");
        list.addFirst("C++");  // 在头部添加元素
        list.addLast("Ruby");  // 在尾部添加元素
        
        // 输出LinkedList
        System.out.println("LinkedList中的元素: " + list);
        
        // 获取指定位置的元素
        System.out.println("第2个元素: " + list.get(1));
        
        // 删除指定元素
        list.remove("Python");
        System.out.println("删除'Python'后的LinkedList: " + list);
        
        // 删除并返回第一个元素
        System.out.println("删除第一个元素: " + list.removeFirst());
        
        // 获取并删除最后一个元素
        System.out.println("删除最后一个元素: " + list.removeLast());
        
        // 获取LinkedList的大小
        System.out.println("LinkedList的大小: " + list.size());
        
        // 判断LinkedList是否为空
        System.out.println("LinkedList是否为空? " + list.isEmpty());
        
        // 遍历LinkedList
        System.out.println("遍历LinkedList:");
        for (String language : list) {
            System.out.println(language);
        }
    }
}

输出结果:

LinkedList中的元素: [C++, Java, Python, JavaScript, Ruby]
第2个元素: Java
删除'Python'后的LinkedList: [C++, Java, JavaScript, Ruby]
删除第一个元素: C++
删除最后一个元素: Ruby
LinkedList的大小: 3
LinkedList是否为空? false
遍历LinkedList:
Java
JavaScript

  在这个例子中,我们展示了如何在LinkedList中进行插入、删除、访问、遍历等基本操作。你可以看到,我们不仅在列表的尾部和头部添加了元素,还展示了如何删除特定元素、获取并删除列表的第一个和最后一个元素。

LinkedList的性能与复杂度

  • 插入和删除

    • 头部或尾部插入/删除:时间复杂度为O(1),非常高效。
    • 中间插入/删除:时间复杂度为O(n),需要遍历链表来找到插入或删除的位置。
  • 访问元素

    • 随机访问get()set()):时间复杂度为O(n),因为需要从头节点或尾节点开始遍历链表到达指定位置。
  • 内存消耗:由于每个节点需要额外存储两个指针(指向前一个和下一个节点),LinkedList的内存消耗比ArrayList更大。

LinkedList vs ArrayList

  • 插入和删除LinkedList在插入和删除操作上比ArrayList更高效,尤其是在列表的两端(头部和尾部)。而ArrayList在插入和删除操作时需要移动数组中的元素,因此其效率较低。

  • 访问效率ArrayList在访问元素时的效率更高,因为它可以通过索引直接访问数组中的元素,时间复杂度为O(1)。而LinkedList需要从头节点或尾节点开始遍历,时间复杂度为O(n)

  • 内存开销LinkedList的内存开销较大,因为每个节点需要额外的指针存储空间。而ArrayList只需要存储数组中的元素,因此内存开销较小。

  • 应用场景:如果你的操作主要是插入和删除元素,尤其是在列表的两端,LinkedList是更好的选择。如果你主要执行随机访问操作,那么ArrayList会提供更高的性能。

总结

  LinkedList是一个功能强大的集合类,它在插入和删除元素时具有非常高的效率,尤其适用于需要频繁进行插入和删除操作的场景。尽管它在访问元素时的效率相对较低,并且在内存消耗上也较ArrayList高,但在特定的应用场景下,LinkedList的性能优势是显而易见的。

  通过理解LinkedList的工作原理和适用场景,你可以更好地选择合适的数据结构,以提高你的Java应用程序的性能。

举报

相关推荐

0 条评论