考虑:

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

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


当前回答

维基百科中提到的foreach循环的概念如下:

然而,与其他for循环构造不同,foreach循环通常保持没有明确的反击:他们基本上说“这样做而不是“做x次”。这样可以避免潜在的一个错误,使代码更容易阅读。

因此,foreach循环的概念描述了该循环不使用任何显式计数器,这意味着不需要使用索引在列表中遍历,因此它将用户从一个错误中解脱出来。为了描述这一错误的一般概念,让我们举一个使用索引在列表中遍历的循环的例子。

// In this loop it is assumed that the list starts with index 0
for(int i=0; i<list.length; i++){

}

但是假设列表以索引1开始,那么这个循环将抛出一个异常,因为它将在索引0处找不到元素,这个错误被称为off-by-one错误。因此,为了避免这一错误,使用了foreach循环的概念。可能还有其他优点,但这就是我认为使用foreach循环的主要概念和优点。

其他回答

这里有一个答案,它不假定了解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等对象有效。

Java中的for each循环使用底层迭代器机制。因此,它与以下内容相同:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}

每个的构造也对数组有效。例如

String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" };

for (String fruit : fruits) {
    // fruit is an element of the `fruits` array.
}

这基本上等同于

for (int i = 0; i < fruits.length; i++) {
    String fruit = fruits[i];
    // fruit is an element of the `fruits` array.
}

因此,总体总结如下:[nsayer]以下是正在发生的事情的较长形式:

for(Iterator<String>i=someList.iiterator();i.hasNext();){字符串项=i.next();System.out.println(项);}注意,如果您需要使用i.移除();或访问实际的迭代器不能使用for(:)习惯用法,因为实际的迭代器只是推断。

[丹尼斯·布埃诺]

nsayer的回答暗示了这一点,但是值得注意的是,OP用于(..)当“someList”为任何实现的东西java.lang.Iterable--它没有成为列表,或来自甚至你自己的类型,因此,可以与此一起使用语法。

在Java 8之前,您需要使用以下功能:

Iterator<String> iterator = someList.iterator();

while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

然而,通过在Java8中引入Streams,您可以用更少的语法完成同样的任务。例如,对于someList,您可以执行以下操作:

someList.stream().forEach(System.out::println);

你可以在这里找到更多关于溪流的信息。

forEach的替代方案,以避免“for each”:

List<String> someList = new ArrayList<String>();

变体1(普通):

someList.stream().forEach(listItem -> {
    System.out.println(listItem);
});

变体2(并行执行(更快)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});