考虑:

List<String> someList = new ArrayList<String>();
// add "monkey", "donkey", "skeleton key" to someList
for (String item : someList) {
    System.out.println(item);
}

如果不使用for each语法,等价的for循环会是什么样子?


当前回答

Java for each循环(也称为增强的for循环)是for循环的简化版本。优点是编写的代码更少,管理的变量更少。缺点是无法控制步长值,也无法访问循环体中的循环索引。

当阶跃值是简单的1增量,并且您只需要访问当前循环元素时,最好使用它们。例如,如果需要在数组或集合中的每个元素上循环,而不在当前元素的前面或后面偷看。

没有循环初始化,没有布尔条件,步长值是隐式的,是一个简单的增量。这就是为什么它们被认为比常规for循环简单得多。

增强的for循环遵循以下执行顺序:

1) 环形体

2) 从步骤1开始重复,直到遍历了整个数组或集合

示例–整数数组

int [] intArray = {1, 3, 5, 7, 9};
for(int currentValue : intArray) {
  System.out.println(currentValue);
}

currentValue变量保存在intArray数组中循环的当前值。请注意,没有显式的步长值——它总是以1为增量。

冒号可以被认为是“in”的意思。因此,增强的for循环声明声明:循环intArray并将当前数组int值存储在currentValue变量中。

输出:

1
3
5
7
9

示例–字符串数组

我们可以使用for each循环遍历字符串数组。循环声明声明:循环myStringsString数组并将当前String值存储在currentString变量中。

String [] myStrings  = {
  "alpha",
  "beta",
  "gamma",
  "delta"
};

for(String currentString : myStrings) {
  System.out.println(currentString);
}

输出:

alpha
beta
gamma
delta

示例–列表

增强的for循环还可以用于迭代java.util.List,如下所示:

List<String> myList = new ArrayList<String>();
myList.add("alpha");
myList.add("beta");
myList.add("gamma");
myList.add("delta");

for(String currentItem : myList) {
  System.out.println(currentItem);
}

循环声明声明:循环myList List of Strings并将当前List值存储在currentItem变量中。

输出:

alpha
beta
gamma
delta

示例–集合

增强的for循环还可以用于迭代java.util.Set,如下所示:

Set<String> mySet = new HashSet<String>();
mySet.add("alpha");
mySet.add("alpha");
mySet.add("beta");
mySet.add("gamma");
mySet.add("gamma");
mySet.add("delta");

for(String currentItem : mySet) {
  System.out.println(currentItem);
}

循环声明声明:循环mySet字符串集,并将当前Set值存储在currentItem变量中。注意,因为这是一个Set,所以不会存储重复的String值。

输出:

alpha
delta
beta
gamma

来源:Java中的循环–终极指南

其他回答

这是一个等价的表达式。

for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
    System.out.println(sit.next());
}
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}

正如许多其他答案正确指出的那样,for each循环只是同一个旧for循环的语法糖,编译器将其转换为同一个老for循环。

javac(OpenJDK)有一个开关-XD printflat,它生成一个Java文件,去掉了所有语法糖。完整的命令如下所示:

javac -XD-printflat -d src/ MyFile.java

//-d is used to specify the directory for output java file

所以让我们去掉语法糖

为了回答这个问题,我创建了一个文件,并为每个文件编写了两个版本,一个带有数组,另一个带有列表。我的Java文件如下所示:

import java.util.*;

public class Temp{

    private static void forEachArray(){
        int[] arr = new int[]{1,2,3,4,5};
        for(int i: arr){
            System.out.print(i);
        }
    }

    private static void forEachList(){
        List<Integer> list = Arrays.asList(1,2,3,4,5);
        for(Integer i: list){
            System.out.print(i);
        }
    }
}

当我用上面的开关编译这个文件时,我得到了以下输出。

import java.util.*;

public class Temp {

    public Temp() {
        super();
    }

    private static void forEachArray() {
        int[] arr = new int[]{1, 2, 3, 4, 5};
        for (/*synthetic*/ int[] arr$ = arr, len$ = arr$.length, i$ = 0; i$ < len$; ++i$) {
            int i = arr$[i$];
            {
                System.out.print(i);
            }
        }
    }

    private static void forEachList() {
        List list = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5)});
        for (/*synthetic*/ Iterator i$ = list.iterator(); i$.hasNext(); ) {
            Integer i = (Integer)i$.next();
            {
                System.out.print(i);
            }
        }
    }
}

您可以看到,与其他语法糖(Autoboxing)一起,每个循环都被更改为简单循环。

这里有一个答案,它不假定了解Java迭代器。它不太精确,但对教育有用。

在编程时,我们通常编写如下代码:

char[] grades = ....
for(int i = 0; i < grades.length; i++) {   // for i goes from 0 to grades.length
    System.out.print(grades[i]);           // Print grades[i]
}

foreach语法允许以更自然、更少语法噪音的方式编写这种常见模式。

for(char grade : grades) {   // foreach grade in grades
    System.out.print(grade); // print that grade
}

此外,此语法对于不支持数组索引但实现Java Iterable接口的Lists或Set等对象有效。

foreach循环语法为:

for (type obj:array) {...}

例子:

String[] s = {"Java", "Coffe", "Is", "Cool"};
for (String str:s /*s is the array*/) {
    System.out.println(str);
}

输出:

Java
Coffe
Is
Cool

警告:可以使用foreach循环访问数组元素,但不能初始化它们。为此使用原始for循环。

警告:必须将数组的类型与其他对象匹配。

for (double b:s) // Invalid-double is not String

如果要编辑元素,请使用原始for循环,如下所示:

for (int i = 0; i < s.length-1 /*-1 because of the 0 index */; i++) {
    if (i==1) //1 because once again I say the 0 index
        s[i]="2 is cool";
    else
        s[i] = "hello";
}

现在,如果我们将数据转储到控制台,我们会得到:

hello
2 is cool
hello
hello