Java List集合详解:选择合适的数据结构!

举报
喵手 发表于 2025/08/24 17:23:59 2025/08/24
【摘要】 开篇语哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,...

开篇语

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在Java的集合框架中,List接口是一个非常常用的集合类型,它代表了一个有序的元素集合。与其他集合不同,List集合允许重复元素并保证元素的插入顺序。Java中有多种List的实现类,其中最常用的包括ArrayListLinkedListVector等。理解它们的实现原理、性能特点以及使用场景,将帮助你选择最合适的集合类,从而提升程序的效率和性能。

在本篇文章中,我们将深入探讨List集合的实现原理,分析ArrayListLinkedList的底层实现,比较VectorArrayList的区别,最后还会进行性能分析,帮助你做出合适的选择。

1. List集合基础:概述与应用

在Java中,List是一个接口,提供了对元素的有序操作。常见的List实现类有:

  • ArrayList:基于动态数组实现,适用于查找频繁、插入和删除较少的场景。
  • LinkedList:基于双向链表实现,适用于插入和删除操作频繁的场景。
  • Vector:类似于ArrayList,但线程安全,性能较差。

List接口常用方法:

  • add(E e):将元素添加到列表的末尾。
  • get(int index):根据索引获取列表中的元素。
  • remove(int index):删除指定位置的元素。
  • size():返回列表中的元素个数。
  • contains(Object o):判断列表中是否包含指定的元素。

2. ArrayList实现原理和源码分析

ArrayListList接口的一个常用实现,底层使用数组来存储元素。它提供了高效的随机访问,但对于插入和删除操作,尤其是在中间位置,性能较差,因为涉及到数组的元素移动。

ArrayList底层结构:

  • ArrayList的底层是一个Object数组,通过数组来存储元素。数组大小会根据需要动态扩展。
  • 默认初始容量为10,当数组满时,ArrayList会自动扩展数组的大小,通常是原数组大小的1.5倍
  • 在扩容时,ArrayList会创建一个新的数组,并将原数组中的元素复制到新数组中。

扩容机制:

ArrayList的数组存满时,它会通过以下方式进行扩容:

private void grow(int minCapacity) {
    // 扩容至原数组大小的1.5倍
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);  // 扩容为原来的1.5倍
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    elementData = Arrays.copyOf(elementData, newCapacity);
}

ArrayList性能分析:

  • 查询操作(get:O(1),直接通过数组索引访问,效率很高。
  • 插入操作:O(n),当在中间插入元素时,后面的元素需要进行移动,导致时间复杂度为O(n)。
  • 删除操作:O(n),类似于插入操作,删除时后面的元素需要移动。

示例代码:

ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
System.out.println(list.get(0)); // 输出 Apple

3. LinkedList实现原理

LinkedList是另一种实现List接口的类,它使用双向链表来存储元素。与ArrayList不同,LinkedList在插入和删除操作上更为高效,尤其是当操作位于链表的开头或中间时,因为它不需要移动元素。

LinkedList底层结构:

  • LinkedList的底层是双向链表,每个元素(节点)包含三个部分:

    • 数据元素。
    • 指向前一个元素的引用。
    • 指向下一个元素的引用。

    这样可以方便地进行插入和删除操作。

性能分析:

  • 查询操作(get:O(n),由于需要从链表的头或尾开始遍历到指定位置,因此效率较低。
  • 插入操作:O(1),在链表头、尾或指定位置进行插入时,时间复杂度是常数级别的。
  • 删除操作:O(1),与插入类似,删除操作的时间复杂度为常数级别。

示例代码:

LinkedList<String> list = new LinkedList<>();
list.add("Apple");
list.add("Banana");
System.out.println(list.get(0)); // 输出 Apple

4. Vector和ArrayList的区别

VectorArrayList都实现了List接口,底层都使用了动态数组来存储元素。但它们之间有一些关键的区别:

线程安全性:

  • VectorVector是线程安全的,所有的方法都被sychronized关键字修饰,这意味着它的每个操作都能保证线程安全。
  • ArrayListArrayList非线程安全的。虽然它没有内置的同步机制,但它的性能在单线程环境下更优。

扩容机制:

  • VectorVector的扩容是按照原数组的2倍进行扩展,这使得在空间不够时,Vector会增加更多的内存。
  • ArrayListArrayList的扩容机制是按照1.5倍进行扩展,相对来说更加保守。

性能差异:

  • 由于Vector的同步机制,它的性能相对较低,适用于多线程环境下对线程安全有要求的场景。
  • ArrayList在单线程环境下性能更好,且使用更为广泛。

示例代码:

Vector<String> vector = new Vector<>();
vector.add("Apple");
vector.add("Banana");

ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("Apple");
arrayList.add("Banana");

5. List集合的选择和性能分析

在选择使用List集合时,我们需要根据实际的业务需求和性能要求来做决策。下面是根据不同场景的性能比较和建议:

1. 查找操作频繁,插入删除不频繁:ArrayList

  • 优点ArrayList提供O(1)的随机访问时间,适用于频繁查找的场景。
  • 缺点:插入和删除时需要移动元素,因此性能较差。

2. 插入和删除操作频繁:LinkedList

  • 优点LinkedList在插入和删除操作上的时间复杂度为O(1),适合频繁进行插入和删除的场景。
  • 缺点:查找操作较慢,需要O(n)时间。

3. 需要线程安全的集合:VectorCopyOnWriteArrayList

  • 优点Vector提供线程安全的操作,但性能较差。如果需要线程安全的ListCopyOnWriteArrayList可能是更好的选择,尤其是在读操作远多于写操作时。
  • 缺点:同步会带来一定的性能开销。

4. 不考虑线程安全性:ArrayList

  • 优点:性能高,适合大多数单线程环境下的使用。
  • 缺点:不提供线程安全性,如果多个线程同时操作,可能会导致数据不一致。

性能比较:

操作类型 ArrayList LinkedList Vector
查询 O(1) O(n) O(1)
插入头部 O(n) O(1) O(n)
插入尾部 O(1) O(1) O(n)
删除头部 O(n) O(1) O(n)
删除尾部 O(1) O(1) O(n)
扩容 O(n)(1.5倍) O(n) O(n)(2倍)

结语:选择合适的List实现,提升程序性能

List集合是Java开发中非常常见的数据结构,理解不同List实现类的原理、性能特点以及使用场景,将帮助你做出更好的选择。在频繁查询的场景下,ArrayList无疑是最好的选择;而在需要频繁插入或删除元素时,LinkedList则是更合适的选择;如果你需要线程安全的操作,可以考虑使用Vector或者CopyOnWriteArrayList。总之,选择合适的List集合类型,可以帮助你更高效地实现需求,提升程序性能。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。


版权声明:本文由作者原创,转载请注明出处,谢谢支持!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。