从入门到精通:五种 List 遍历方法对比与实战指南

简介: 小米是一位热爱分享技术的程序员,本文详细介绍了 Java 中遍历 List 的五种方式:经典 for 循环、增强 for 循环、Iterator 和 ListIterator、Stream API 以及 forEach 方法。每种方式都有其适用场景和优缺点,例如 for 循环适合频繁访问索引,增强 for 循环和 forEach 方法代码简洁,Stream API 适合大数据量操作,ListIterator 支持双向遍历。文章通过生动的小故事和代码示例,帮助读者更好地理解和选择合适的遍历方式。



哈喽,大家好!我是小米,一个热爱分享技术的大哥哥,今天要和大家聊聊我们日常写代码绕不开的一个话题——如何遍历一个 List。虽然这是基础中的基础,但正因为它常见,咱们更要把这个基础打牢,毕竟“地基稳了,房子才能盖得高”嘛。

小伙伴们平时在写代码时,可能最常用的就是 for 循环或者增强 for 循环来遍历 List,对吧?可你有没有想过,Java 中遍历 List 的方式有几种?它们的实现原理是什么?哪种方式在特定场景下表现更好?别急,今天我们就通过几个小故事,把这个问题彻底说清楚。

遍历方式一:经典的 for 循环

小故事:忙碌的快递员

想象一下,我们的 List 是一排快递箱,而我们需要逐一检查这些快递。用 for 循环就像雇了一个快递员,按照箱子的编号(索引)一个个检查。

代码实现:

实现原理

for 循环通过索引访问每一个元素,list.get(i) 会调用 List 接口实现的 get() 方法。对于 ArrayList,这个方法是 O(1) 的,因为它直接访问底层数组。而对于 LinkedList,则是 O(n) 的,因为它需要从头开始遍历链表找到对应的元素。

优缺点

  • 优点:灵活,可以访问索引。
  • 缺点:如果使用的是 LinkedList,性能可能不佳。

遍历方式二:增强 for 循环(for-each)

小故事:机器人搬运工

快递员太累了,我们换成了机器人。机器人不关心快递的编号,只要把每个箱子搬出来即可。

代码实现:

实现原理

增强 for 循环底层依赖的是 Iterator。当你写下 for (String item : list) 时,Java 编译器会将它转换为一个 Iterator 对象并调用其 hasNext() next() 方法。

例如,编译后大致相当于:

优缺点

  • 优点:代码简洁,适合遍历所有元素。
  • 缺点:无法访问索引,不能灵活修改 List。

遍历方式三:Iterator 和 ListIterator

小故事:双向传送带

有些场景下,机器人需要走到某个快递箱时突然回头,比如需要倒着检查快递的标签。这时候,就需要一种更灵活的工具——IteratorListIterator

代码实现:

实现原理

  • Iterator:通过 hasNext() 和 next() 依次获取元素,它是单向的。
  • ListIterator:是 Iterator 的增强版,支持双向遍历,提供了 hasPrevious() 和 previous() 方法。

优缺点

  • 优点:Iterator 提供了 fail-fast 机制,能在集合结构被修改时及时抛出 ConcurrentModificationException。
  • 缺点:操作较繁琐,尤其是需要双向遍历时。

遍历方式四:Stream API

小故事:流水线工厂

时代进步了,我们用上了自动化流水线。快递箱在流水线上一个个通过,系统自动处理。

代码实现:

实现原理

Stream 是 Java 8 引入的一个功能,它并没有改变 List 本身,而是提供了一种对集合操作的声明式方式。stream() 会生成一个 Stream 对象,forEach() 方法对每个元素应用给定的操作。

优缺点

  • 优点:代码优雅,支持并行流处理,适合大数据量操作。
  • 缺点:在简单场景下可能显得“杀鸡用牛刀”。

遍历方式五:forEach 方法

小故事:语音助手登场

如果想让快递员听命于语音助手,直接告诉他“依次打开每个箱子”,那么就可以使用 List 自带的 forEach 方法。

代码实现:

实现原理

forEach 是 Java 8 中添加到 Iterable 接口的默认方法。底层原理与增强 for 循环类似,但代码更加简洁。

优缺点

  • 优点:语法简洁,直观易懂。
  • 缺点:和增强 for 循环一样,不支持访问索引。

哪种方式最优?最佳实践来啦!

性能分析

  • 如果需要频繁访问索引(比如访问特定元素或跳过某些元素),优先使用经典的 for 循环。
  • 如果不关心索引,增强 for 循环和 forEach 方法更适合,代码简洁。
  • 在需要操作大量数据或并行处理时,Stream API 是最佳选择。
  • 对于双向遍历,非 ListIterator 莫属。

小米的建议

  • 优雅为主,性能为辅:在大多数业务场景中,性能差异可以忽略,优先选择简洁且可读性高的方式。
  • 避免 LinkedList 坑:如果你不知道具体的 List 类型,尽量少用经典的 for 循环。
  • 注意 fail-fast:如果遍历时需要修改 List,请使用 Iterator,避免出现意料之外的 ConcurrentModificationException。

END

从经典的 for 循环到现代化的 Stream API,Java 提供了多种遍历方式,每种方式各有优劣。选择哪种方式不仅取决于你习惯写哪种代码,还取决于业务场景的具体需求。

小伙伴们,如果你觉得今天的文章有帮助,不妨点个赞或者转发一下,让更多人看到!你平时最常用哪种方式遍历 List?有没有遇到过哪些奇葩的坑?评论区一起聊聊吧~

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号软件求生,获取更多技术干货!

相关文章
|
4月前
|
存储 Java
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
Java学习笔记 List集合的定义、集合的遍历、迭代器的使用
|
2月前
|
Java 程序员 编译器
Java|如何正确地在遍历 List 时删除元素
从源码分析如何正确地在遍历 List 时删除元素。为什么有的写法会导致异常,而另一些不会。
44 3
|
4月前
|
XML Java API
List与String相互转化方法汇总
本文汇总了List与String相互转化的多种方法,包括使用`String.join()`、`StringBuilder`、Java 8的Stream API、Apache Commons Lang3的`StringUtils.join()`以及Guava的`Joiner.on()`方法实现List转String;同时介绍了使用`split()`方法、正则表达式、Apache Commons Lang3的`StringUtils.split()`及Guava的`Splitter.on()`方法实现String转List。
158 1
List与String相互转化方法汇总
|
2月前
|
存储 C++ 容器
C++入门9——list的使用
C++入门9——list的使用
22 0
|
2月前
|
存储 缓存 应用服务中间件
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
Nginx入门 -- 基本数据结构中之ngx_list_t,ngx_queue_t
40 0
|
4月前
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
48 5
|
4月前
|
存储 NoSQL 算法
Redis6入门到实战------ 三、常用五大数据类型(列表(List)、集合(Set)、哈希(Hash)、Zset(sorted set))
这是关于Redis 6入门到实战的文章,具体内容涉及Redis的五大数据类型:列表(List)、集合(Set)、哈希(Hash)、有序集合(Zset(sorted set))。文章详细介绍了这些数据类型的特点、常用命令以及它们背后的数据结构。如果您有任何关于Redis的具体问题或需要进一步的帮助,请随时告诉我。
|
5月前
|
前端开发 Java 项目管理
List.of 问题之使用List.of方法为什么会引发前端解析失败的问题,如何解决
List.of 问题之使用List.of方法为什么会引发前端解析失败的问题,如何解决
|
5月前
|
XML Java API
List与String相互转化的方法有哪些
摘要:本文概述了Java中List转换为String及反之的多种策略。使用`String.join()`可简洁地连接List元素;`StringBuilder`提供灵活控制;Java 8 Stream API收集器简化操作;Apache Commons Lang3的`StringUtils.join()`和Guava的`Joiner.on()`支持外部库的高效转换。
102 2
|
6月前
|
安全 Java
java线程之List集合并发安全问题及解决方案
java线程之List集合并发安全问题及解决方案
1043 1