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);
}

总结

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

相关文章

  • java isInterrupted()判断线程的实例讲解

    java isInterrupted()判断线程的实例讲解

    在本篇内容里小编给大家分享的是一篇关于java isInterrupted()判断线程的实例讲解内容,有兴趣的朋友们可以学习下。
    2021-05-05
  • 详解Java的Hibernate框架中的缓存与二级缓存

    详解Java的Hibernate框架中的缓存与二级缓存

    这篇文章主要介绍了Java的Hibernate框架中的缓存与二级缓存,Hibernate是Java的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-12-12
  • SpringBoot Security使用MySQL实现验证与权限管理

    SpringBoot Security使用MySQL实现验证与权限管理

    安全管理是软件系统必不可少的的功能。根据经典的“墨菲定律”——凡是可能,总会发生。如果系统存在安全隐患,最终必然会出现问题,这篇文章主要介绍了SpringBoot安全管理Spring Security基本配置
    2022-11-11
  • 详解Spring Cloud中Hystrix的请求合并

    详解Spring Cloud中Hystrix的请求合并

    这篇文章主要介绍了详解Spring Cloud中Hystrix的请求合并,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Java文件目录下载并打包成ZIP压缩包

    Java文件目录下载并打包成ZIP压缩包

    这篇文章主要介绍了在Java中如何实现文件夹、文件目录的递归下载并打包成ZIP压缩包,文中的示例代码讲解详细,有需要的可以参考下
    2024-10-10
  • Java中遍历Map的多种方法示例及优缺点总结

    Java中遍历Map的多种方法示例及优缺点总结

    在java中遍历Map有不少的方法,下面这篇文章主要给大家介绍了关于Java中遍历Map的多种方法,以及各种方法的优缺点总结,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-07-07
  • 一文搞懂Spring Bean中的作用域和生命周期

    一文搞懂Spring Bean中的作用域和生命周期

    Spring作为当前Java最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。了解Spring Bean的作用域与生命周期是非常必要的,快跟随小编一起学习学习吧
    2022-06-06
  • 这一次搞懂Spring的XML解析原理说明

    这一次搞懂Spring的XML解析原理说明

    这篇文章主要介绍了这一次搞懂Spring的XML解析原理说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • java多线程join()方法的作用和实现原理解析(应用场景)

    java多线程join()方法的作用和实现原理解析(应用场景)

    join方法主要是用于将当前线程挂起,等待其他线程结束后在执行当前线程,本文通过应用场景分析代码示例讲解java多线程join()方法的作用和实现原理,感兴趣的朋友一起看看吧
    2021-07-07
  • 修改SpringBoot 中MyBatis的mapper.xml文件位置的过程详解

    修改SpringBoot 中MyBatis的mapper.xml文件位置的过程详解

    由于MyBatis默认的mapper.xml的扫描位置是resource文件下,但是不可能整个项目的mapper.xml文件都放在resource下,如果文件较少还行,但是如果文件比较多,太麻烦了,所以本文给大家介绍了修改SpringBoot 中MyBatis的mapper.xml文件位置的过程,需要的朋友可以参考下
    2024-08-08

最新评论