杰瑞科技汇

foreach 数组 java

Java 中主要有两种方式来实现 foreach 风格的循环:

  1. 增强 for 循环 (Enhanced for loop):这是最常用、最推荐的方式,从 Java 5 (JDK 1.5) 开始引入。
  2. 使用 Stream API:这是一种更现代、函数式的方式,从 Java 8 开始引入,功能更强大,尤其是在进行复杂的数据处理时。

增强 for 循环 (Enhanced for loop)

这是最直接、最简洁的 foreach 实现,语法非常清晰。

语法

for (元素类型 元素变量 : 遍历对象) {
    // 循环体,在这里可以访问元素变量
}
  • 元素类型:数组中每个元素的类型。
  • 元素变量:一个临时变量,在每次循环中,它会自动接收数组中的一个元素的值。
  • 遍历对象:要遍历的数组。

示例

下面是一个完整的例子,演示如何遍历一个 String 数组和一个 int 数组。

public class ForeachArrayExample {
    public static void main(String[] args) {
        // 1. 遍历 String 数组
        String[] fruits = {"Apple", "Banana", "Cherry", "Date"};
        System.out.println("--- 遍历水果数组 ---");
        // 使用增强 for 循环
        for (String fruit : fruits) {
            System.out.println("水果: " + fruit);
        }
        System.out.println("\n--- 遍历数字数组 ---");
        // 2. 遍历 int 数组
        int[] numbers = {10, 20, 30, 40, 50};
        // 使用增强 for 循环
        for (int number : numbers) {
            System.out.println("数字: " + number);
        }
    }
}

输出结果:

--- 遍历水果数组 ---
水果: Apple
水果: Banana
水果: Cherry
水果: Date
--- 遍历数字数组 ---
数字: 10
数字: 20
数字: 30
数字: 40
数字: 50

优点

  • 代码简洁:语法简单,易于阅读,避免了传统 for 循环中复杂的索引管理。
  • 不易出错:不需要关心数组的起始索引、结束索引和索引递增,减少了 ArrayIndexOutOfBoundsException 的风险。
  • 专注于元素本身:让你更专注于对每个元素进行什么操作,而不是如何获取元素。

缺点(与传统 for 循环对比)

增强 for 循环虽然方便,但它有一个重要的限制:你无法获取当前元素的索引,也无法在遍历过程中修改数组本身(只能修改元素的副本)。

场景对比:

场景 增强型 for 循环 传统 for 循环
遍历并打印元素 非常适合 也可以,但稍显冗长
需要知道元素的索引 无法做到 非常适合 (i 就是索引)
需要修改数组中的元素 只能修改元素的副本,无法影响原数组 非常适合 (array[i] = newValue;)
需要反向遍历 无法做到 非常适合 (for (int i = array.length - 1; i >= 0; i--))
需要跳过某些元素 无法做到 非常适合 (if (i % 2 == 0) continue;)

示例:无法修改原数组

int[] scores = {95, 88, 76, 100};
// 使用增强 for 循环尝试修改分数
for (int score : scores) {
    score = 0; // 这只是修改了 score 这个临时变量的值,原数组 scores 中的元素不变
}
System.out.println(Arrays.toString(scores)); // 输出: [95, 88, 76, 100]

使用传统 for 循环修改原数组:

int[] scores = {95, 88, 76, 100};
// 使用传统 for 循环修改分数
for (int i = 0; i < scores.length; i++) {
    scores[i] = 0; // 直接通过索引修改原数组
}
System.out.println(Arrays.toString(scores)); // 输出: [0, 0, 0, 0]

使用 Stream API (Java 8+)

对于更复杂的场景,比如过滤、转换、聚合等,使用 Stream API 会非常强大和优雅。

示例

import java.util.Arrays;
public class StreamArrayExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        System.out.println("--- 使用 Stream API 遍历 ---");
        // 1. 简单遍历
        Arrays.stream(numbers).forEach(number -> System.out.println("数字: " + number));
        System.out.println("\n--- Stream API 高级操作示例 ---");
        // 2. 过滤出偶数并打印
        System.out.println("所有偶数:");
        Arrays.stream(numbers)
              .filter(n -> n % 2 == 0) // 过滤条件
              .forEach(System.out::println); // 方法引用,等同于 n -> System.out.println(n)
        // 3. 计算所有偶数的和
        int sumOfEvens = Arrays.stream(numbers)
                               .filter(n -> n % 2 == 0)
                               .sum();
        System.out.println("\n所有偶数的和是: " + sumOfEvens);
    }
}

输出结果:

--- 使用 Stream API 遍历 ---
数字: 1
数字: 2
数字: 3
数字: 4
数字: 5
数字: 6
数字: 7
数字: 8
数字: 9
数字: 10
--- Stream API 高级操作示例 ---
所有偶数:
2
4
6
8
10
所有偶数的和是: 30

Stream API 的优点

  • 函数式编程:代码更声明式,你只需要“做什么”,而不需要关心“怎么做”。
  • 强大的链式操作:可以像流水线一样组合多个操作(如 filter, map, sorted, forEach 等)。
  • 并行处理:只需将 stream() 换成 parallelStream(),就可以轻松实现并行计算,提高大数据量下的处理速度。

Stream API 的缺点

  • 开销较大:对于简单的遍历,Stream API 的性能开销比增强 for 循环要大。
  • 代码稍复杂:对于初学者,其语法可能不如增强 for 循环直观。

总结与选择

特性 增强型 for 循环 Stream API 传统 for 循环
简洁性 ⭐⭐⭐⭐⭐ (最高) ⭐⭐⭐ (复杂操作时高) ⭐⭐ (需要索引时)
可读性 ⭐⭐⭐⭐⭐ (最高) ⭐⭐⭐⭐ (函数式风格) ⭐⭐⭐ (逻辑清晰)
功能 仅遍历 遍历、过滤、转换、聚合等 任何操作,包括修改原数组、获取索引
性能 ⭐⭐⭐⭐⭐ (最高) ⭐⭐ (简单遍历时) ⭐⭐⭐⭐ (通常很好)
适用场景 简单的从头到尾遍历,不关心索引 复杂的数据处理、函数式风格 需要索引、需要修改原数组、需要复杂控制逻辑

如何选择?

  1. 如果你只是想简单地遍历数组中的每一个元素,不关心索引,也不需要修改数组本身

    • 首选增强型 for 循环,它最简单、最安全、性能最好。
  2. 如果你需要对数组元素进行复杂的操作,比如过滤、转换、计算总和、查找最大值等

    • 使用 Stream API,它更强大、更灵活,代码更优雅。
  3. 如果你在遍历过程中需要知道元素的索引,或者需要修改数组中的元素

    • 使用传统 for 循环,这是唯一能直接满足这些需求的标准方式。
分享:
扫描分享到社交APP
上一篇
下一篇