百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT知识 > 正文

能懂系列之 List 集合详解

liuian 2025-01-14 15:19 57 浏览



今天咱们来谈一谈 java 的 list 集合吧,进入正题之前呢,咱们聊点题外话吧。前几天在工作中使用到了 map 的嵌套,也就是一个 map 的 value 是另一个 map, 这个由于是第一次接触呢,所以当时这个逻辑还是比较混乱的,因为不知道如果改了外层的 map , 内层的 value 会不会随之改变,后来做了好几个实例才发现不会,因为外层 map 的 key 所对应的 value 值都是和 key 绑定的,所以其实和一般的 map 的逻辑是一样的,这个等我之后有空的话再详细讲一讲吧。

好了,言归正传吧,下面正式进去今天的主题 --- List

那么,问题来了,什么是 list 呢,list 的特性和使用方法种种的又是什么呢,接下来就让我一点一点的来说吧。

List 是什么?

首先,咱们来说说什么是 List 吧!

集合类是 Java 数据结构的实现。Java 的集合类是 java.util 包中的重要内容,它允许以各种方式将元素分组,并定义了各种使这些元素更容易操作的方法。Java 集合类是 Java 将一些基本的和使用频率极高的基础类进行封装和增强后再以一个类的形式提供。集合类是可以往里面保存多个对象的类,存放的是对象,不同的集合类有不同的功能和特点,适合不同的场合,用以解决一些实际问题。

以上,是百度百科对于 List 集合的说明。通俗地讲 List 就是一个存放数据的容器,他根据你存储的顺序来给对应的索引值,而索引呢,也是你用来取出值的一个标识。

List 的继承结构

List 的继承结构

上面那张图没有过多的花里胡哨,可以让我们很清晰的看出集合的一个大概的继承体系,然而我们今天只看 Collection 下的 list 接口以及其实现类,因为我们今儿就是研究它来了。

特有功能

List 集合是一个元素有序(每个元素都有对应的顺序索引,第一个元素索引为 0)、且可重复的集合。

List 是 Collection 接口的子接口,故而拥有 Collection 的所有方法。除此之外呢,还有一些对索引操作的方法。

今天我们主要说的还是 List 的实现类,毕竟它很常用。

List 整体

从上图,可以让我们对于 List 的三个实现类有一个大概的了解.

分类

1、ArrayList

ArrayList 是一个数组队列,相当于 「动态数组」。与 Java 中的数组相比,它的容量能动态增长。它继承于 AbstractList,实现了 List, RandomAccess(随机访问), Cloneable(克隆), java.io.Serializable(可序列化)这些接口.

ArrayList 继承了 AbstractList,实现了 List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能.

ArrayList 实现了 RandmoAccess 接口,即提供了随机访问功能。RandmoAccess 是 java 中用来被 List 实现,为 List 提供快速访问功能的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问.

ArrayList 实现了 Cloneable 接口,即覆盖了函数 clone (),能被克隆。ArrayList 实现 java.io.Serializable 接口,这意味着 ArrayList 支持序列化,能通过序列化去传输.

ArrayList 的底层数据结构因为是数组,故而查询快,增删慢,线程不安全,效率高,可以存储重复元素。下面来看看 ArrayList 常用的一些方法吧。

1.1、add 方法:

向集合中插入数据,集合的索引下标是从 0 开始.

1.2、插入数据

向指定位置插入数据,两个参数,一个是索引,一个是数据,插入后这个索引后面的数据向后顺延.

1.3、删除数据

删除集合中的数据,参数是数据对应的索引值.

1.4、返回索引值.

指定元素再 list 集合中的位置,返回索引值.

1.5、set

替换 List 中对应位置的值,两个参数分别是索引及新的数据,此操作的返回值是被替换的数据.

1.6、get

返回指定索引的数据

1.7、addAll

新增集合操作,两个参数:插入的位置索引,插入的集合

1.8、lastIndexOf

返回元素最后一次出现的位置索引

1.9、subList

截取指定位置的数据,两个参数:开始位置的索引,结束位置的索引

上面所有代码的运行结果如下图:

好了,相信讲完这些大家会对 ArrayList 的使用有了一些比较具体的了解了。

不过厚此薄彼不好,下面我们来说说 List 的另外两个实现类吧,不过主要就是说一下它们和 ArrayList 的一个区别及它们本身的优势吧.

2、LinkedList

LinkedList 可以看做为一个双向链表,所有的操作都可以认为是一个双向链表的操作,因为它实现了 Deque 接口和 List 接口。同样,LinkedList 也是线程不安全的,如果在并发环境下使用它,同样用 Colletions 类中的静态方法 synchronizedList () 对 LinkedList 进行调用即可. LinkedList 与 ArrayList 最大的区别是 LinkedList 更加灵活,并且部分方法的效率比 ArrayList 对应方法的效率要高很多,对于数据频繁出入的情况下,并且要求操作要足够灵活,建议使用 LinkedList;对于数组变动不大,主要是用来查询的情况下,可以使用 ArrayList。

LinkedList 常用方法:

  • toArray (): 以正确的顺序(从第一个到最后一个)返回一个包含此列表中所有元素的数组
  • size (): 返回此列表中的元素数
  • set (int index,E element): 用指定的元素替换此列表中指定位置的元素
  • removeLast (): 从此列表中删除并返回最后一个元素
  • removeFirst (): 从此列表中删除并返回第一个元素
  • remove (int index): 删除该列表中指定位置的元素
  • getFirst (): 返回此列表中的第一个元素
  • getLast (): 返回此列表中的最后一个元素
  • get (int index): 返回此列表中指定位置的元素
  • add (E element): 将指定的元素追加到此列表的末尾
  • add (int index,E element): 在此列表中的指定位置插入指定的元素
  • addFirst (E element): 在该列表开头插入指定的元素
  • addLast (E element) : 将指定的元素追加到此列表的末尾
  • clear (): 从列表中删除所有元素

3、Vector

Vector 也是一个类似于 ArrayList 的可变长度的数组类型,它的内部也是使用数组来存放数据对象的。值得注意的是 Vector 与 ArrayList 唯一的区别是,Vector 是线程安全的,即它的大部分方法都包含有关键字 synchronized. 因此,若对于单一线程的应用来说,最好使用 ArrayList 代替 Vector,因为这样效率会快很多(类似的情况有 StringBuffer 与 StringBuilder);而在多线程程序中,为了保证数据的同步和一致性,可以使用 Vector 代替 ArrayList 实现同样的功能.「Vector 常用方法:」

  • add (E element): 将指定的元素追加到此 Vector 的末尾
  • add (int index,E element):在此 Vector 中的指定位置插入指定的元素
  • elementAt (int index): 返回指定索引处的组件
  • get (int index): 返回此向量中指定位置的元素
  • removeElementAt (int index): 删除指定索引处的组件
  • removeRange (int fromIndex,int toIndex):从此列表中删除所有索引为 fromIndex (含)和 toIndex 之间的元素

上面大体说了说 List 集合中另外两种实现类的一些基本详情,最后,既然是一系列的数据,那么必然会面临一个遍历的问题,所有本文的最后我们来看一看 List 的遍历方式 (其实只是 ArrayList 的遍历方式).

3.1、通过迭代器遍历。即通过 Iterator 去遍历.

List<String> list = new ArrayList();
        list.add(new String("book001"));
        list.add(new String("book002"));
        list.add(new String("book003 "));
        String value = null;
        Iterator iter = list.iterator();
        while (iter.hasNext()) {
            value = (String)iter.next();
            System.out.println(value);
        }

结果展示:

3.2、随机访问 index, 通过索引值去遍历.

由于 ArrayList 实现了 RandomAccess 接口,它支持通过索引值去随机访问元素.

List<String> list = new ArrayList();
        list.add(new String("book004"));
        list.add(new String("book005"));
        list.add(new String("book006 "));
        String value = null;
        int size = list.size();
        for (int i=0; i<size; i++) {
            value = (String)list.get(i);
            System.out.println(value);
        }

结果展示:

3.3、增强 for (foreach) 循环遍历

List<String> list = new ArrayList();
        list.add(new String("book007"));
        list.add(new String("book008"));
        list.add(new String("book009"));
        String value = null;
        for (String books:list) {
            value = books;
            System.out.println(value);
        }

结果展示:

小结

List 中元素是有序的,元素可以重复,因为该集合体有索引

ArrayList:

  • 底层数据结构是数组,查询快,增删慢。
  • 线程不安全,效率高。
  • 当元素放满了后,默认以原长度的 50%+1 的长度加长集合容器的长度。

LinkedList:

  • 底层数据结构是链表,查询慢,增删快。
  • 线程不安全,效率高。
  • Vector (线程安全的) 相对 ArrayList 查询慢
  • Vector 相对 LinkedList 增删慢 (数组结构)

Vector:

  • 底层数据结构是数组,查询快,增删慢。
  • 线程安全,效率低。
  • 当元素放满了后,默认以原长度 100% 的长度加长集合容器的长度

好啦,今天的关于 list 集合的一些知识就讲解结束啦,有什么错误或不足欢迎大家留言指正,程序员的路上并肩前行吧。

作者丨阿淼

来源丨微信公众号:Java学习之道

相关推荐

eino v0.4.5版本深度解析:接口类型处理优化与错误机制全面升级

近日,eino框架发布了v0.4.5版本,该版本在错误处理、类型安全、流处理机制以及代理配置注释等方面进行了多项优化与修复。本次更新共包含6个提交,涉及10个文件的修改,由2位贡献者共同完成。本文将详...

SpringBoot异常处理_springboot异常注解

在SpringBoot中,异常处理是构建健壮、可维护Web应用的关键部分。良好的异常处理机制可以统一返回格式、提升用户体验、便于调试和监控。以下是SpringBoot中处理异常的完整指...

Jenkins运维之路(Jenkins流水线改造Day02-1-容器项目)

这回对线上容器服务器的流水线进行了一定的改造来满足目前线上的需求,还是会将所有的自动化脚本都放置到代码库中统一管理,我感觉一章不一定写的完,所以先给标题加了个-1,话不多说开干1.本次流水线的流程设计...

告别宕机!零基础搭建服务器监控告警系统!小白也能学会!

前言本文将带你从零开始,一步步搭建一个完整的服务器指标监控与邮件告警系统,使用的技术栈均为业界主流、稳定可靠的开源工具:Prometheus:云原生时代的监控王者,擅长指标采集与告警规则定义Node_...

httprunner实战接口测试笔记,拿走不谢

每天进步一点点,关注我们哦,每天分享测试技术文章本文章出自【码同学软件测试】码同学公众号:自动化软件测试码同学抖音号:小码哥聊软件测试01开始安装跟创建项目pipinstallhttprunne...

基于JMeter的性能压测平台实现_jmeter压测方案

这篇文章已经是两年前写的,短短两年时间,JMeter开源应用技术的发展已经是翻天覆地,最初由github开源项目zyanycall/stressTestPlatform形成的这款测试工具也开始慢...

12K+ Star!新一代的开源持续测试工具!

大家好,我是Java陈序员。在企业软件研发的持续交付流程中,测试环节往往是影响效率的关键瓶颈,用例管理混乱、接口调试复杂、团队协作不畅、与DevOps流程脱节等问题都能影响软件交付。今天,给大家...

Spring Boot3 中分库分表之后如何合并查询

在当今互联网应用飞速发展的时代,数据量呈爆发式增长。对于互联网软件开发人员而言,如何高效管理和查询海量数据成为了一项关键挑战。分库分表技术应运而生,它能有效缓解单库单表数据量过大带来的性能瓶颈。而在...

离线在docker镜像方式部署ragflow0.17.2

经常项目上会出现不能连外网的情况,要怎么使用ragflow镜像部署呢,这里提供详细的步骤。1、下载基础镜像根据docker-compose-base.yml及docker-compose.yml中的i...

看,教你手写一个最简单的SpringBoot Starter

何为Starter?想必大家都使用过SpringBoot,在SpringBoot项目中,使用最多的无非就是各种各样的Starter了。那何为Starter呢?你可以理解为一个可拔插式...

《群星stellaris》军事基地跳出怎么办?解决方法一览

《群星stellaris》军事基地跳出情况有些小伙伴出现过这种情况,究竟该怎么解决呢?玩家“gmjdadk”分享的自己的解决方法,看看能不能解决。我用英文原版、德语、法语和俄语四个版本对比了一下,结果...

数据开发工具dbt手拉手教程-03.定义数据源模型

本章节介绍在dbt项目中,如何定义数据源模型。定义并引入数据源通过Extract和Load方式加载到仓库中的数据,可以使用dbt中的sources组件进行定义和描述。通过在dbt中将这些数据集(表)声...

docker compose 常用命令手册_docker-compose init

以下是DockerCompose常用命令手册,按生命周期管理、服务运维、构建配置、扩缩容、调试工具分类,附带参数解析、示例和关键说明,覆盖多容器编排核心场景:一、生命周期管理(核心命令...

RagFlow与DeepSeek R1本地知识库搭建详细步骤及代码实现

一、环境准备硬件要求独立显卡(建议NVIDIAGPU,8GB显存以上)内存16GB以上,推荐32GB(处理大规模文档时更高效)SSD硬盘(加速文档解析与检索)软件安装bash#必装组件Docker...

Docker Compose 配置更新指南_docker-compose配置

高效管理容器配置变更的最佳实践方法重启范围保留数据卷适用场景docker-composeup-d变更的服务常规配置更新--force-recreate指定/所有服务强制重建down→up流程...