Java for-each循环(遍历循环)详解

 更新时间:2025年07月14日 08:47:25   作者:晚夜微雨问海棠呀  
本文详解Java for-each循环,涵盖其简化遍历、类型安全、不可变性、空指针防护等特性,适用场景及限制,错误案例与修正,性能对比,高级技巧(如Java14 Records),并提供最佳实践指南

一、本质与语法

// 标准语法 (Java 5+)
for (ElementType element : Iterable/Array) {
    // 操作element
}

// 等效传统实现
Iterator<ElementType> it = collection.iterator();
while (it.hasNext()) {
    ElementType element = it.next();
    // 操作element
}

设计目标:简化集合/数组遍历,消除显式迭代器操作

底层机制

  • Iterable对象:自动调用iterator()获取迭代器
  • 对数组:转换为传统索引循环(编译后字节码可见)

二、核心特性

强制类型安全

List<String> list = Arrays.asList("A", "B");
for (Integer num : list) {} // 编译错误:类型不匹配

不可变性保证

for (final String s : list) { 
    s = "new"; // 编译错误:final修饰符
}

空指针防护

for (Object obj : null) { ... } // 运行时抛出NullPointerException

三、适用场景与限制

支持的数据结构不支持的操作场景
所有实现Iterable的集合遍历时删除元素(需用Iterator.remove())
数组需要反向遍历
自定义可迭代对象需要同时访问索引

四、典型错误案例

并发修改异常

List<String> list = new ArrayList<>(Arrays.asList("A", "B"));
for (String s : list) {
    list.remove(s); // 抛出ConcurrentModificationException
}

✅ 修正方案:改用迭代器遍历 + remove()

对象引用陷阱

List<StringBuilder> list = new ArrayList<>();
list.add(new StringBuilder("Hello"));
for (StringBuilder sb : list) {
    sb.append(" World"); // 修改对象内部状态 ✔️
    sb = new StringBuilder(); // 仅改变局部引用 ✖️
}

五、性能对比分析

数据结构for-each传统for循环推荐方案
ArrayList迭代器遍历(稍慢)索引直接访问(快)大数据量选传统式
LinkedList迭代器遍历(快)索引遍历(O(n²))必须用for-each
HashSet唯一安全遍历方式无法直接使用索引强制使用for-each

六、高级应用技巧

多维数组遍历

int[][] matrix = {{1,2}, {3,4}};
for (int[] row : matrix) {
    for (int num : row) {
        System.out.print(num + " ");
    }
}

自定义可迭代对象

class MyIterable implements Iterable<String> {
    public Iterator<String> iterator() {
        return Arrays.asList("A","B").iterator();
    }
}

并行遍历优化(Java 8+)

list.parallelStream().forEach(element -> {
    // 多线程处理(注意线程安全)
});

七、最佳实践指南

优先选择场景

  • 只读遍历操作
  • 无需索引的线性访问
  • 代码可读性要求高

规避风险策略

// 防御性复制(针对可能被修改的集合)
for (String s : new ArrayList<>(originalList)) {
    originalList.remove(s); // 安全操作
}

类型推断优化(Java 10+)

var entries = Map.of(1,"A",2,"B").entrySet();
for (var entry : entries) {
    System.out.println(entry.getKey() + ":" + entry.getValue());
}

深度扩展:Java 14引入的Records类型可与for-each循环完美配合:

record Point(int x, int y) {}
List<Point> points = List.of(new Point(1,2), new Point(3,4));
for (Point(var x, var y) : points) { // 模式匹配解构(Java 17预览特性)
    System.out.println(x + "," + y);
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 简单了解Thymeleaf语法 数据延迟加载使用实例

    简单了解Thymeleaf语法 数据延迟加载使用实例

    这篇文章主要介绍了简单了解Thymeleaf语法 数据延迟加载使用实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2010-05-05
  • 详解IDEA中MAVEN项目打JAR包的简单方法

    详解IDEA中MAVEN项目打JAR包的简单方法

    本篇文章主要介绍了详解IDEA中MAVEN项目打JAR包的简单方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • SpringBoot集成redis实现共享存储session

    SpringBoot集成redis实现共享存储session

    这篇文章主要介绍了SpringBoot集成redis实现共享存储session的流程步骤,文中通过代码示例介绍的非常详细,并总结了一些常见的错误及解决方法,需要的朋友可以参考下
    2024-03-03
  • 深入讲解Java synchronized的核心原理

    深入讲解Java synchronized的核心原理

    这篇文章主要为大家详细介绍了Java中synchronized的核心原理以及简单的用法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-07-07
  • Springboot结合Mybatis-Plus实现业务撤销回滚功能

    Springboot结合Mybatis-Plus实现业务撤销回滚功能

    本文介绍了如何在Springboot结合Mybatis-Plus实现业务撤销回滚功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-12-12
  • Java基础类之ArrayUtils工具类详解

    Java基础类之ArrayUtils工具类详解

    这篇文章主要介绍了java.ArrayDeque类使用方法,java.ArrayDeque类提供了可调整大小的阵列,并实现了Deque接口,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Java并发容器ConcurrentLinkedQueue解析

    Java并发容器ConcurrentLinkedQueue解析

    这篇文章主要介绍了Java并发容器ConcurrentLinkedQueue解析,
    2023-12-12
  • 如何优雅的进行Spring整合MongoDB详解

    如何优雅的进行Spring整合MongoDB详解

    这篇文章主要给大家介绍了如何优雅的进行Spring整合MongoDB的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-02-02
  • 基于Maven pom文件使用分析

    基于Maven pom文件使用分析

    本文详细介绍了Maven项目的核心配置文件pom.xml的结构和各个元素的用途,包括项目基础信息、依赖管理、仓库配置、构建配置、版本控制、分发和报告配置等,帮助读者全面了解Maven项目的构建和管理过程
    2024-12-12
  • Java Guava的使用技巧整理

    Java Guava的使用技巧整理

    Guava是Google发布的一个开源库,主要提供了一些在Java开发中非常有用的工具类和API,不管是工作还是学习都是非常值得我们去熟悉的,一起来看看吧
    2023-03-03

最新评论