杰瑞科技汇

ArrayList Java遍历有哪些高效方法?

假设我们有以下 ArrayList 作为示例:

ArrayList Java遍历有哪些高效方法?-图1
(图片来源网络,侵删)
import java.util.ArrayList;
import java.util.List;
public class ArrayListTraversal {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Orange");
        fruits.add("Mango");
    }
}

经典 for 循环 (索引遍历)

这是最传统、最基础的遍历方式,通过索引来访问每一个元素。

代码示例:

System.out.println("--- 方法一:经典 for 循环 ---");
for (int i = 0; i < fruits.size(); i++) {
    String fruit = fruits.get(i);
    System.out.println(fruit);
}

优点:

  • 直观易懂:对于初学者来说非常容易理解。
  • 随机访问:如果循环体内需要根据索引进行其他操作(获取前一个或后一个元素),这种方式非常方便。
  • 兼容性好:适用于所有版本的 Java。

缺点:

ArrayList Java遍历有哪些高效方法?-图2
(图片来源网络,侵删)
  • 代码冗余:需要手动管理索引变量 i
  • 性能问题:对于 LinkedList get(i) 方法性能很差(需要从头遍历),虽然 ArrayListget(i) 是 O(1) 时间复杂度,但这种方式本身不具备通用性。

增强 for 循环 (For-Each 循环)

这是 Java 5 引入的特性,专门用于遍历集合和数组,语法简洁,是目前最推荐的遍历方式。

代码示例:

System.out.println("\n--- 方法二:增强 for 循环 (For-Each) ---");
for (String fruit : fruits) {
    System.out.println(fruit);
}

优点:

  • 代码简洁:语法非常优雅,可读性高。
  • 不易出错:无需关心索引的边界条件,避免了 ArrayIndexOutOfBoundsException
  • 性能优秀:对于 ArrayList,其内部实现和经典 for 循环性能几乎完全相同。

缺点:

ArrayList Java遍历有哪些高效方法?-图3
(图片来源网络,侵删)
  • 无法获取索引:如果循环体内需要知道当前元素的索引,此方法不适用。
  • 无法修改集合本身:不能在遍历过程中安全地使用 remove() 方法删除元素(会抛出 ConcurrentModificationException),如果需要删除元素,请使用方法三或方法四。

迭代器 (Iterator)

迭代器是专门为集合遍历而设计的接口,它提供了一种“安全”的方式来遍历和修改集合。

代码示例:

System.out.println("\n--- 方法三:迭代器 ---");
// 获取迭代器
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
    String fruit = iterator.next();
    System.out.println(fruit);
    // 示例:安全地删除元素
    // if ("Orange".equals(fruit)) {
    //     iterator.remove(); // 使用迭代器的 remove() 方法是安全的
    // }
}

重要提示:

  • remove() 的正确用法:如果你想遍历时删除元素,必须调用 iterator.remove(),而不是 list.remove()list.remove() 会快速失败,抛出 ConcurrentModificationException

优点:

  • 最安全:是唯一可以在遍历过程中安全地删除元素的官方方式。
  • 通用性强:适用于所有实现了 Collection 接口的集合(包括 LinkedList, HashSet 等),无论它们是否支持随机访问。
  • 解耦:将遍历逻辑与集合的底层实现分离开来。

缺点:

  • 代码稍显冗长:相比 For-Each 循环,代码量稍多。

Java 8+ Stream API

这是 Java 8 引入的函数式编程特性,功能非常强大,不仅可以遍历,还可以进行过滤、映射、聚合等各种复杂操作。

代码示例:

System.out.println("\n--- 方法四:Stream API ---");
// 1. 简单遍历
fruits.stream().forEach(fruit -> System.out.println(fruit));
// 2. 结合过滤和遍历(只打印长度大于 5 的水果)
System.out.println("\n--- Stream API 结合过滤 ---");
fruits.stream()
      .filter(fruit -> fruit.length() > 5) // 过滤条件
      .forEach(fruit -> System.out.println(fruit)); // 对过滤后的元素执行操作

优点:

  • 功能强大:非常适合进行链式调用,实现复杂的集合处理逻辑。
  • 代码简洁(复杂场景下):当需要处理和转换数据时,一行代码可以完成传统多行代码的工作。
  • 并行处理:只需将 stream() 换成 parallelStream(),即可轻松实现并行处理,提升大数据量下的性能。

缺点:

  • 开销稍大:对于简单的遍历,相比传统方式会有微小的性能开销。
  • 学习曲线:对于不熟悉函数式编程的开发者来说,需要一定的学习成本。

总结与选择建议

方法 代码示例 优点 缺点 适用场景
经典 for 循环 for (int i=0; i<list.size(); i++) 直观,可获取索引 代码冗余,通用性差 需要使用索引进行操作时
增强 for 循环 for (T item : list) 简洁,易读,性能好 无法获取索引,不能安全删除 日常遍历的首选,绝大多数遍历场景
迭代器 while (iterator.hasNext()) 可安全删除,通用性强 代码稍长 需要在遍历过程中添加或删除元素时
Stream API list.stream().forEach(...) 功能强大,可并行,易链式调用 有开销,学习成本高 需要进行复杂的数据处理、过滤、转换

  • 只是想简单地、从头到尾地打印或处理每个元素?

    • 使用增强 for 循环 (For-Each),这是最简单、最直接、最高效的选择。
  • 需要在遍历的时候删除某些元素?

    • 使用迭代器,并调用 iterator.remove()
  • 需要对集合进行更复杂的操作,比如筛选、转换、排序、统计等?

    • 使用 Stream API,这是现代 Java 开发的趋势。
  • 在循环中需要用到元素的索引?

    • 使用经典 for 循环
分享:
扫描分享到社交APP
上一篇
下一篇