详细来说,“foreach”是如何实现的? Java 中的循环工作?

发布于 2024-07-04 08:59:22 字数 706 浏览 13 评论 0原文

考虑一下:

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

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


刚接触 Java 的人在尝试使用新样式的 foreach 循环修改原始数据时通常会遇到问题。 使用 为什么在 foreach 循环中分配给迭代变量不会更改基础数据? 来关闭有关该常见问题的重复项。 请注意,具有类似结构的其他语言通常也存在相同的问题; 例如,对于 Python 中的同一问题,请参阅 为什么修改迭代变量不会影响后续迭代?

Consider:

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

What would the equivalent for loop look like without using the for each syntax?


People new to Java commonly encounter issues when trying to modify the original data using the new style foreach loop. Use Why doesn't assigning to the iteration variable in a foreach loop change the underlying data? to close duplicates about that common problem. Note that other languages with analogous constructs generally have the same issue; for example, see Why doesn't modifying the iteration variable affect subsequent iterations? for the same issue in Python.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(29

ペ泪落弦音 2024-07-11 08:59:22

使用forEach

int[] numbers = {1,2,3,4,5};

Arrays.stream(numbers).forEach(System.out::println);

响应:

1
2
3
4
5

The process finished with exit code 0

PS:您需要一个数组(int[]numbers),并import java.util.Arrays;

Using forEach:

int[] numbers = {1,2,3,4,5};

Arrays.stream(numbers).forEach(System.out::println);

Response:

1
2
3
4
5

The process finished with exit code 0

PS: You need a Array (int[] numbers), and import java.util.Arrays;

那些过往 2024-07-11 08:59:22

JLSfor-each 循环可以有两种形式:

  1. 如果表达式的类型是 Iterable 的子类型,则翻译如下:

    列表<字符串>   someList = new ArrayList(); 
      someList.add(“苹果”); 
      someList.add("球"); 
      for (字符串项: someList) { 
          System.out.println(item); 
      } 
    
      // 翻译为: 
    
      for(Iterator; stringIterator = someList.iterator(); stringIterator.hasNext(); ) { 
          字符串项 = stringIterator.next(); 
          System.out.println(item); 
      } 
      
  2. 如果表达式必须具有数组类型 T[],则:

    String[] someArray = new String[2]; 
      someArray[0] = "苹果"; 
      someArray[1] = "球"; 
    
      for(String item2 : someArray) { 
          System.out.println(item2); 
      } 
    
      // 翻译为: 
      for (int i = 0; i < someArray.length; i++) { 
          字符串 item2 = someArray[i]; 
          System.out.println(item2); 
      } 
      

Java 8 引入了流,通常在数据集大小合适的情况下表现更好。 我们可以将它们用作:

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

As defined in JLS, a for-each loop can have two forms:

  1. If the type of expression is a subtype of Iterable then translation is as:

    List<String> someList = new ArrayList<String>();
    someList.add("Apple");
    someList.add("Ball");
    for (String item : someList) {
        System.out.println(item);
    }
    
    // Is translated to:
    
    for(Iterator<String> stringIterator = someList.iterator(); stringIterator.hasNext(); ) {
        String item = stringIterator.next();
        System.out.println(item);
    }
    
  2. If the expression necessarily has an array type T[] then:

    String[] someArray = new String[2];
    someArray[0] = "Apple";
    someArray[1] = "Ball";
    
    for(String item2 : someArray) {
        System.out.println(item2);
    }
    
    // Is translated to:
    for (int i = 0; i < someArray.length; i++) {
        String item2 = someArray[i];
        System.out.println(item2);
    }
    

Java 8 has introduced streams which perform generally better with a decent size dataset. We can use them as:

someList.stream().forEach(System.out::println);
Arrays.stream(someArray).forEach(System.out::println);
趴在窗边数星星i 2024-07-11 08:59:22

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

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

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

The for-each loop in Java uses the underlying iterator mechanism. So it's identical to the following:

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

while (iterator.hasNext()) {
  String item = iterator.next();
  System.out.println(item);
}
傻比既视感 2024-07-11 08:59:22

Java for every 循环(又名增强型 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 循环来迭代字符串数组。 循环声明指出:循环遍历 myStrings String 数组并将当前 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 字符串列表并存储当前列表值 <在 currentItem 变量中。

输出:

alpha
beta
gamma
delta

示例 – Set

增强的 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 中的循环 - 终极指南

The Java for each loop (aka enhanced for loop) is a simplified version of a for loop. The advantage is that there is less code to write and less variables to manage. The downside is that you have no control over the step value and no access to the loop index inside the loop body.

They are best used when the step value is a simple increment of 1 and when you only need access to the current loop element. For example, if you need to loop over every element in an array or Collection without peeking ahead or behind the current element.

There is no loop initialization, no boolean condition and the step value is implicit and is a simple increment. This is why they are considered so much simpler than regular for loops.

Enhanced for loops follow this order of execution:

1) loop body

2) repeat from step 1 until entire array or collection has been traversed

Example – Integer Array

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

The currentValue variable holds the current value being looped over in the intArray array. Notice there’s no explicit step value – it’s always an increment by 1.

The colon can be thought of to mean “in”. So the enhanced for loop declaration states: loop over intArray and store the current array int value in the currentValue variable.

Output:

1
3
5
7
9

Example – String Array

We can use the for-each loop to iterate over an array of strings. The loop declaration states: loop over myStrings String array and store the current String value in the currentString variable.

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

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

Output:

alpha
beta
gamma
delta

Example – List

The enhanced for loop can also be used to iterate over a java.util.List as follows:

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

The loop declaration states: loop over myList List of Strings and store the current List value in the currentItem variable.

Output:

alpha
beta
gamma
delta

Example – Set

The enhanced for loop can also be used to iterate over a java.util.Set as follows:

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

The loop declaration states: loop over mySet Set of Strings and store the current Set value in the currentItem variable. Notice that since this is a Set, duplicate String values are not stored.

Output:

alpha
delta
beta
gamma

Source: Loops in Java – Ultimate Guide

春庭雪 2024-07-11 08:59:22

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

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.
}

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

for(Iterator i = someList.iterator(); i.hasNext(); ) { 
    字符串项 = i.next(); 
    System.out.println(item); 
  } 
  

请注意,如果您需要使用
i. 删除(); 在你的循环中,或访问
以某种方式实际的迭代器,你
不能使用 for( : ) 习惯用法,因为
实际的迭代器只是
推断。

[丹尼斯·布埃诺]

nsayer 的回答暗示了这一点,但是
值得注意的是OP的for(..)
当“someList”为时语法将起作用
任何实现
java.lang.Iterable——它没有
是一个列表,或者是一些集合
java.util。 即使是你自己的类型,
因此,可以与此一起使用
语法。

The construct for each is also valid for arrays. e.g.

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

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

which is essentially equivalent of

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

So, overall summary:
[nsayer] The following is the longer form of what is happening:

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

Note that if you need to use
i.remove(); in your loop, or access
the actual iterator in some way, you
cannot use the for( : ) idiom, since
the actual Iterator is merely
inferred.

[Denis Bueno]

It's implied by nsayer's answer, but
it's worth noting that the OP's for(..)
syntax will work when "someList" is
anything that implements
java.lang.Iterable -- it doesn't have
to be a list, or some collection from
java.util. Even your own types,
therefore, can be used with this
syntax.

喜你已久 2024-07-11 08:59:22

for-each 循环,添加在 < a href="http://docs.oracle.com/javase/1.5.0/docs/guide/language/index.html" rel="noreferrer">Java 5 (也称为“增强的 for 循环"),相当于使用 java.lang. util.Iterator——它是同一事物的语法糖。 因此,在逐个按顺序读取每个元素时,应始终选择 for-each 而不是迭代器,因为它更方便、更简洁。

For-each

for (int i : intList) {
   System.out.println("An element in the list: " + i);
}

Iterator

Iterator<Integer> intItr = intList.iterator();
while (intItr.hasNext()) {
   System.out.println("An element in the list: " + intItr.next());
}

在某些情况下,您必须直接使用Iterator。 例如,尝试在使用 for-each 时删除元素会(将?)导致 ConcurrentModificationException

For-each 与 for-loop:基本差异

for-loop 和 for-each 之间唯一的实际差异是,对于可索引对象,您无权访问索引。 需要基本 for 循环的示例:

for (int i = 0; i < array.length; i++) {
   if(i < 5) {
      // Do something special
   }  else {
      // Do other stuff
   }
}

虽然您可以使用 for-each 手动创建单独的索引 int 变量,但

int idx = -1;
for (int i : intArray) {
   idx++;
   ...
}

...不推荐,因为 variable-scope 并不理想,基本的 for 循环只是此用途的标准和预期格式案件。

For-each 与 for-loop:性能

访问集合时,for-each 是 比基本 for 循环的数组访问快得多。 然而,当访问数组时(至少对于原始数组和包装数组而言),通过索引进行访问要快得多。

计算原始 int 数组的迭代器和索引访问之间的差异

在访问 intInteger 数组时,索引比迭代器快 23-40%。 以下是本文底部测试类的输出,它将 100 个元素的 Primitive-int 数组中的数字相加(A 是迭代器,B 是索引):

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 358,597,622 nanoseconds
Test B: 269,167,681 nanoseconds
B faster by 89,429,941 nanoseconds (24.438799231635727% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 377,461,823 nanoseconds
Test B: 278,694,271 nanoseconds
B faster by 98,767,552 nanoseconds (25.666236154695838% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 288,953,495 nanoseconds
Test B: 207,050,523 nanoseconds
B faster by 81,902,972 nanoseconds (27.844689860906513% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,373,765 nanoseconds
Test B: 283,813,875 nanoseconds
B faster by 91,559,890 nanoseconds (23.891659337194227% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,790,818 nanoseconds
Test B: 220,770,915 nanoseconds
B faster by 155,019,903 nanoseconds (40.75164734599769% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 326,373,762 nanoseconds
Test B: 202,555,566 nanoseconds
B faster by 123,818,196 nanoseconds (37.437545972215744% faster)

我还针对 Integer 运行了这个输出 数组,索引仍然是明显的赢家,但速度只快了 18% 到 25%。

对于集合,迭代器比索引更快。

但是,对于IntegersList,迭代器显然是赢家。 只需将测试类中的 int-array 更改为:

List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});

并对测试函数进行必要的更改(将 int[] 更改为 List, lengthsize() 等):

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)

在一项测试中,它们几乎是等效的,但对于集合,迭代器获胜。

*这篇文章基于我在 Stack Overflow 上写的两个答案:

更多信息:for-each 循环还是迭代器哪个更高效?

我创建的完整测试类

比较了所需时间-阅读此后的-to-do-any-two-things类关于 Stack Overflow 的问题:

import  java.text.NumberFormat;
import  java.util.Locale;

/**
   <P>{@code java TimeIteratorVsIndexIntArray 1000000}</P>

   @see  <CODE><A HREF="https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java">https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java</A></CODE>
 **/
public class TimeIteratorVsIndexIntArray {

    public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);

    public static final void main(String[] tryCount_inParamIdx0) {
        int testCount;

        // Get try-count from a command-line parameter
        try {
           testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
        }
        catch(ArrayIndexOutOfBoundsException | NumberFormatException x) {
           throw  new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
        }

        //Test proper...START
        int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};

        long lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testIterator(intArray);
        }

        long lADuration = outputGetNanoDuration("A", lStart);

        lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testFor(intArray);
        }

        long lBDuration = outputGetNanoDuration("B", lStart);

        outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
    }

    private static final void testIterator(int[] int_array) {
       int total = 0;
       for(int i = 0; i < int_array.length; i++) {
          total += int_array[i];
       }
    }

    private static final void testFor(int[] int_array) {
       int total = 0;
       for(int i : int_array) {
          total += i;
       }
    }
    //Test proper...END

    //Timer testing utilities...START
    public static final long outputGetNanoDuration(String s_testName, long l_nanoStart) {
        long lDuration = System.nanoTime() - l_nanoStart;
        System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
        return  lDuration;
    }

    public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName) {
        long lDiff = -1;
        double dPct = -1.0;
        String sFaster = null;
        if(l_aDuration > l_bDuration) {
            lDiff = l_aDuration - l_bDuration;
            dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
            sFaster = "B";
        }
        else {
            lDiff = l_bDuration - l_aDuration;
            dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
            sFaster = "A";
        }
        System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
        return  lDiff;
   }

   //Timer testing utilities...END

}

The for-each loop, added in Java 5 (also called the "enhanced for loop"), is equivalent to using a java.util.Iterator--it's syntactic sugar for the same thing. Therefore, when reading each element, one by one and in order, a for-each should always be chosen over an iterator, as it is more convenient and concise.

For-each

for (int i : intList) {
   System.out.println("An element in the list: " + i);
}

Iterator

Iterator<Integer> intItr = intList.iterator();
while (intItr.hasNext()) {
   System.out.println("An element in the list: " + intItr.next());
}

There are situations where you must use an Iterator directly. For example, attempting to delete an element while using a for-each can (will?) result in a ConcurrentModificationException.

For-each vs. for-loop: Basic differences

The only practical difference between for-loop and for-each is that, in the case of indexable objects, you do not have access to the index. An example when the basic for-loop is required:

for (int i = 0; i < array.length; i++) {
   if(i < 5) {
      // Do something special
   }  else {
      // Do other stuff
   }
}

Although you could manually create a separate index int-variable with for-each,

int idx = -1;
for (int i : intArray) {
   idx++;
   ...
}

...it is not recommended, since variable-scope is not ideal, and the basic for loop is simply the standard and expected format for this use case.

For-each vs. for-loop: Performance

When accessing collections, a for-each is significantly faster than the basic for loop's array access. When accessing arrays, however--at least with primitive and wrapper-arrays--access via indexes is dramatically faster.

Timing the difference between iterator and index access for primitive int-arrays

Indexes are 23-40 percent faster than iterators when accessing int or Integer arrays. Here is the output from the testing class at the bottom of this post, which sums the numbers in a 100-element primitive-int array (A is iterator, B is index):

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 358,597,622 nanoseconds
Test B: 269,167,681 nanoseconds
B faster by 89,429,941 nanoseconds (24.438799231635727% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 377,461,823 nanoseconds
Test B: 278,694,271 nanoseconds
B faster by 98,767,552 nanoseconds (25.666236154695838% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 288,953,495 nanoseconds
Test B: 207,050,523 nanoseconds
B faster by 81,902,972 nanoseconds (27.844689860906513% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,373,765 nanoseconds
Test B: 283,813,875 nanoseconds
B faster by 91,559,890 nanoseconds (23.891659337194227% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 375,790,818 nanoseconds
Test B: 220,770,915 nanoseconds
B faster by 155,019,903 nanoseconds (40.75164734599769% faster)

[C:\java_code\]java TimeIteratorVsIndexIntArray 1000000
Test A: 326,373,762 nanoseconds
Test B: 202,555,566 nanoseconds
B faster by 123,818,196 nanoseconds (37.437545972215744% faster)

I also ran this for an Integer array, and indexes are still the clear winner, but only between 18 and 25 percent faster.

For collections, iterators are faster than indexes

For a List of Integers, however, iterators are the clear winner. Just change the int-array in the test-class to:

List<Integer> intList = Arrays.asList(new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100});

And make the necessary changes to the test-function (int[] to List<Integer>, length to size(), etc.):

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,429,929,976 nanoseconds
Test B: 5,262,782,488 nanoseconds
A faster by 1,832,852,512 nanoseconds (34.326681820485675% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,907,391,427 nanoseconds
Test B: 3,957,718,459 nanoseconds
A faster by 1,050,327,032 nanoseconds (26.038700083921256% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,566,004,688 nanoseconds
Test B: 4,221,746,521 nanoseconds
A faster by 1,655,741,833 nanoseconds (38.71935684115413% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 2,770,945,276 nanoseconds
Test B: 3,829,077,158 nanoseconds
A faster by 1,058,131,882 nanoseconds (27.134122749113843% faster)

[C:\java_code\]java TimeIteratorVsIndexIntegerList 1000000
Test A: 3,467,474,055 nanoseconds
Test B: 5,183,149,104 nanoseconds
A faster by 1,715,675,049 nanoseconds (32.60101667104192% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,439,983,933 nanoseconds
Test B: 3,509,530,312 nanoseconds
A faster by 69,546,379 nanoseconds (1.4816434912159906% faster)

[C:\java_code\]java TimeIteratorVsIndexIntList 1000000
Test A: 3,451,101,466 nanoseconds
Test B: 5,057,979,210 nanoseconds
A faster by 1,606,877,744 nanoseconds (31.269164666060377% faster)

In one test they're almost equivalent, but with collections, iterator wins.

*This post is based on two answers I wrote on Stack Overflow:

Some more information: Which is more efficient, a for-each loop, or an iterator?

The full testing class

I created this compare-the-time-it-takes-to-do-any-two-things class after reading this question on Stack Overflow:

import  java.text.NumberFormat;
import  java.util.Locale;

/**
   <P>{@code java TimeIteratorVsIndexIntArray 1000000}</P>

   @see  <CODE><A HREF="https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java">https://stackoverflow.com/questions/180158/how-do-i-time-a-methods-execution-in-java</A></CODE>
 **/
public class TimeIteratorVsIndexIntArray {

    public static final NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);

    public static final void main(String[] tryCount_inParamIdx0) {
        int testCount;

        // Get try-count from a command-line parameter
        try {
           testCount = Integer.parseInt(tryCount_inParamIdx0[0]);
        }
        catch(ArrayIndexOutOfBoundsException | NumberFormatException x) {
           throw  new IllegalArgumentException("Missing or invalid command line parameter: The number of testCount for each test. " + x);
        }

        //Test proper...START
        int[] intArray = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100};

        long lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testIterator(intArray);
        }

        long lADuration = outputGetNanoDuration("A", lStart);

        lStart = System.nanoTime();
        for(int i = 0; i < testCount; i++) {
           testFor(intArray);
        }

        long lBDuration = outputGetNanoDuration("B", lStart);

        outputGetABTestNanoDifference(lADuration, lBDuration, "A", "B");
    }

    private static final void testIterator(int[] int_array) {
       int total = 0;
       for(int i = 0; i < int_array.length; i++) {
          total += int_array[i];
       }
    }

    private static final void testFor(int[] int_array) {
       int total = 0;
       for(int i : int_array) {
          total += i;
       }
    }
    //Test proper...END

    //Timer testing utilities...START
    public static final long outputGetNanoDuration(String s_testName, long l_nanoStart) {
        long lDuration = System.nanoTime() - l_nanoStart;
        System.out.println("Test " + s_testName + ": " + nf.format(lDuration) + " nanoseconds");
        return  lDuration;
    }

    public static final long outputGetABTestNanoDifference(long l_aDuration, long l_bDuration, String s_aTestName, String s_bTestName) {
        long lDiff = -1;
        double dPct = -1.0;
        String sFaster = null;
        if(l_aDuration > l_bDuration) {
            lDiff = l_aDuration - l_bDuration;
            dPct = 100.00 - (l_bDuration * 100.0 / l_aDuration + 0.5);
            sFaster = "B";
        }
        else {
            lDiff = l_bDuration - l_aDuration;
            dPct = 100.00 - (l_aDuration * 100.0 / l_bDuration + 0.5);
            sFaster = "A";
        }
        System.out.println(sFaster + " faster by " + nf.format(lDiff) + " nanoseconds (" + dPct + "% faster)");
        return  lDiff;
   }

   //Timer testing utilities...END

}
紫﹏色ふ单纯 2024-07-11 08:59:22

它看起来像这样。 非常粗暴。

for (Iterator<String> i = someList.iterator(); i.hasNext(); )
        System.out.println(i.next());

每个的很好的文章“nofollow noreferrer">Sun 文档

It would look something like this. Very crufty.

for (Iterator<String> i = someList.iterator(); i.hasNext(); )
        System.out.println(i.next());

There is a good writeup on for each in the Sun documentation.

孤云独去闲 2024-07-11 08:59:22
for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
    String item = i.next();
    System.out.println(item);
}

请注意,如果您需要在循环中使用 i.remove();,或者以某种方式访问​​实际的迭代器,则不能使用 for ( : ) 习惯用法,因为实际的迭代器只是推断出来的。

正如 Denis Bueno 所指出的,此代码适用于任何实现 可迭代接口

如果 for (:) 习惯用法的右侧是数组而不是 Iterable 对象,则内部代码使用 int 索引计数器并检查 array.length 代替。 请参阅 Java 语言规范< /a>.

for (int i = 0; i < someArray.length; i++) {
    String item = someArray[i];
    System.out.println(item);
}
for (Iterator<String> i = someIterable.iterator(); i.hasNext();) {
    String item = i.next();
    System.out.println(item);
}

Note that if you need to use i.remove(); in your loop, or access the actual iterator in some way, you cannot use the for ( : ) idiom, since the actual iterator is merely inferred.

As was noted by Denis Bueno, this code works for any object that implements the Iterable interface.

If the right-hand side of the for (:) idiom is an array rather than an Iterable object, the internal code uses an int index counter and checks against array.length instead. See the Java Language Specification.

for (int i = 0; i < someArray.length; i++) {
    String item = someArray[i];
    System.out.println(item);
}
极度宠爱 2024-07-11 08:59:22

在 Java 8 之前,您需要使用以下内容:

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

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

但是,随着 Java 8 中引入 Streams,您可以使用更少的语法完成相同的操作。 例如,对于您的 someList 您可以执行以下操作:

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

您可以找到有关流的更多信息 此处

Prior to Java 8, you need to use the following:

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

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

However, with the introduction of Streams in Java 8 you can do same thing in much less syntax. For example, for your someList you can do:

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

You can find more about streams here.

终止放荡 2024-07-11 08:59:22

它通过消除所有基本的循环混乱来为您的代码增添美感。 它使您的代码看起来很干净,如下所示。

普通 for 循环:

void cancelAll(Collection<TimerTask> list) {
    for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
         i.next().cancel();
}

使用 for-each:

void cancelAll(Collection<TimerTask> list) {
    for (TimerTask t : list)
        t.cancel();
}

for-each 是实现 的集合上的构造>迭代器。 请记住,您的集合应该实现Iterator; 否则你不能将它与 for-each 一起使用。

以下行读作“for every TimerTask t in list.

for (TimerTask t : list)

在 for-each 情况下出错的可能性较小。 您不必担心初始化迭代器或初始化循环计数器并终止它(在存在错误范围的情况下)。

It adds beauty to your code by removing all the basic looping clutter. It gives a clean look to your code, justified below.

Normal for loop:

void cancelAll(Collection<TimerTask> list) {
    for (Iterator<TimerTask> i = list.iterator(); i.hasNext();)
         i.next().cancel();
}

Using for-each:

void cancelAll(Collection<TimerTask> list) {
    for (TimerTask t : list)
        t.cancel();
}

for-each is a construct over a collection that implements Iterator. Remember that, your collection should implement Iterator; otherwise you can't use it with for-each.

The following line is read as "for each TimerTask t in list."

for (TimerTask t : list)

There is less chance for errors in case of for-each. You don't have to worry about initializing the iterator or initializing the loop counter and terminating it (where there is scope for errors).

撧情箌佬 2024-07-11 08:59:22
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}
for (Iterator<String> itr = someList.iterator(); itr.hasNext(); ) {
   String item = itr.next();
   System.out.println(item);
}
风苍溪 2024-07-11 08:59:22

另请注意,在原始问题中使用“foreach”方法确实有一些限制,例如无法在迭代期间从列表中删除项目。

新的 for 循环更易于阅读,并且无需单独的迭代器,但仅在只读迭代过程中真正可用。

Also note that using the "foreach" method in the original question does have some limitations, such as not being able to remove items from the list during the iteration.

The new for-loop is easier to read and removes the need for a separate iterator, but is only really usable in read-only iteration passes.

孤檠 2024-07-11 08:59:22

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

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

变体 1(普通):

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

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

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

An alternative to forEach in order to avoid your "for each":

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

Variant 1 (plain):

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

Variant 2 (parallel execution (faster)):

someList.parallelStream().forEach(listItem -> {
    System.out.println(listItem);
});
身边 2024-07-11 08:59:22

使用较旧的 Java 版本,包括 Java 7,您可以使用 foreach 循环如下。

List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
items.add("E");

for(String item : items) {
    System.out.println(item);
}

以下是在 Java 中使用 for every 循环的最新方法;8(使用 forEach + lambda 表达式或方法引用循环列表)。

Lambda

// Output: A,B,C,D,E
items.forEach(item->System.out.println(item));

方法参考

// Output: A,B,C,D,E
items.forEach(System.out::println);

有关更多信息,请参阅"Java 8 forEach 示例

Using older Java versions, including Java 7, you can use a foreach loop as follows.

List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
items.add("E");

for(String item : items) {
    System.out.println(item);
}

The following is the very latest way of using a for each loop in Java 8 (loop a List with forEach + lambda expression or method reference).

Lambda

// Output: A,B,C,D,E
items.forEach(item->System.out.println(item));

Method reference

// Output: A,B,C,D,E
items.forEach(System.out::println);

For more information, refer to "Java 8 forEach examples".

静若繁花 2024-07-11 08:59:22

这是一个等价的表达式。

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

Here's an equivalent expression.

for(Iterator<String> sit = someList.iterator(); sit.hasNext(); ) {
    System.out.println(sit.next());
}
苍景流年 2024-07-11 08:59:22

维基百科中提到的 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 处找不到元素,并且此错误称为偏一错误。 因此,为了避免这种差一错误,使用了 foreach 循环的概念。 可能还有其他优点,但这就是我认为使用 foreach 循环的主要概念和优点。

The concept of a foreach loop as mentioned in Wikipedia is highlighted below:

Unlike other for loop constructs, however, foreach loops usually
maintain no explicit counter: they essentially say "do this to
everything in this set", rather than "do this x times". This avoids
potential off-by-one errors and makes code simpler to read.

So the concept of a foreach loop describes that the loop does not use any explicit counter which means that there is no need of using indexes to traverse in the list thus it saves user from off-by-one error. To describe the general concept of this off-by-one error, let us take an example of a loop to traverse in a list using indexes.

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

}

But suppose if the list starts with index 1 then this loop is going to throw an exception as it will found no element at index 0 and this error is called an off-by-one error. So to avoid this off-by-one error the concept of a foreach loop is used. There may be other advantages too, but this is what I think is the main concept and advantage of using a foreach loop.

野却迷人 2024-07-11 08:59:22

在 Java 8 中,他们引入了 forEach。 使用List、Maps可以循环。

使用 foreach 循环列表

List<String> someList = new ArrayList<String>();
someList.add("A");
someList.add("B");
someList.add("C");

someList.forEach(listItem -> System.out.println(listItem))

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

使用 foreach 循环地图

Map<String, String> mapList = new HashMap<>();
    mapList.put("Key1", "Value1");
    mapList.put("Key2", "Value2");
    mapList.put("Key3", "Value3");

mapList.forEach((key,value)->System.out.println("Key: " + key + " Value : " + value));

mapList.forEach((key,value)->{
    System.out.println("Key : " + key + " Value : " + value);
});

In Java 8, they introduced forEach. Using it List, Maps can be looped.

Loop a List using for each

List<String> someList = new ArrayList<String>();
someList.add("A");
someList.add("B");
someList.add("C");

someList.forEach(listItem -> System.out.println(listItem))

or

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

Loop a Map using for each

Map<String, String> mapList = new HashMap<>();
    mapList.put("Key1", "Value1");
    mapList.put("Key2", "Value2");
    mapList.put("Key3", "Value3");

mapList.forEach((key,value)->System.out.println("Key: " + key + " Value : " + value));

or

mapList.forEach((key,value)->{
    System.out.println("Key : " + key + " Value : " + value);
});
陌若浮生 2024-07-11 08:59:22

Java“for-each”循环构造将允许对两种类型的对象进行迭代:

  • T[] (任何类型的数组)
  • java.lang.IterableT[] (任何类型的数组) Iterable

接口只有一个方法:Iterator。 迭代器()。 这适用于 Collection 类型的对象,因为 Collection 接口扩展了 Iterable

The Java "for-each" loop construct will allow iteration over two types of objects:

  • T[] (arrays of any type)
  • java.lang.Iterable<T>

The Iterable<T> interface has only one method: Iterator<T> iterator(). This works on objects of type Collection<T> because the Collection<T> interface extends Iterable<T>.

浮生未歇 2024-07-11 08:59:22

在 Java 8 功能中,您可以使用以下功能:

List<String> messages = Arrays.asList("First", "Second", "Third");

void forTest(){
    messages.forEach(System.out::println);
}

输出

First
Second
Third

In Java 8 features you can use this:

List<String> messages = Arrays.asList("First", "Second", "Third");

void forTest(){
    messages.forEach(System.out::println);
}

Output

First
Second
Third
耳根太软 2024-07-11 08:59:22

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

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

hello
2 is cool
hello
hello

A foreach loop syntax is:

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

Example:

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

Output:

Java
Coffe
Is
Cool

WARNING: You can access array elements with the foreach loop, but you can NOT initialize them. Use the original for loop for that.

WARNING: You must match the type of the array with the other object.

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

If you want to edit elements, use the original for loop like this:

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

Now if we dump s to the console, we get:

hello
2 is cool
hello
hello
对不⑦ 2024-07-11 08:59:22

nsayer 的答案暗示了这一点,但它是值得注意的是,当“someList”是实现 java.lang.Iterable 的任何东西时,OP 的 for(..) 语法将起作用——它不必是一个列表,或者来自 java 的一些集合.util。 因此,即使是您自己的类型也可以与此语法一起使用。

It's implied by nsayer's answer, but it's worth noting that the OP's for(..) syntax will work when "someList" is anything that implements java.lang.Iterable -- it doesn't have to be a list, or some collection from java.util. Even your own types, therefore, can be used with this syntax.

腹黑女流氓 2024-07-11 08:59:22

这是一个不假设您了解 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 接口的对象(例如列表或集合)有效。

Here is an answer which does not assume knowledge of Java Iterators. It is less precise, but it is useful for education.

While programming we often write code that looks like the following:

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]
}

The foreach syntax allows this common pattern to be written in a more natural and less syntactically noisy way.

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

Additionally this syntax is valid for objects such as Lists or Sets which do not support array indexing, but which do implement the Java Iterable interface.

|煩躁 2024-07-11 08:59:22

正如许多好的答案所说,如果对象想要使用 for-each 循环,则它必须实现 Iterable 接口

我将发布一个简单的示例,并尝试以不同的方式解释 for-each 循环的工作原理。

for-each 循环示例:

public class ForEachTest {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("111");
        list.add("222");

        for (String str : list) {
            System.out.println(str);
        }
    }
}

然后,如果我们使用 javap 反编译这个类,我们将得到这个字节码样本:

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #16                 // class java/util/ArrayList
         3: dup
         4: invokespecial #18                 // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #19                 // String 111
        11: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #27                 // String 222
        20: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: invokeinterface #29,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;

从样本的最后一行可以看到,编译器会在编译时自动将 for-each 关键字的使用转换为 Iterator 的使用。 这可以解释为什么没有实现 Iterable 接口的对象在尝试使用 for-each 循环时会抛出异常。

As so many good answers said, an object must implement the Iterable interface if it wants to use a for-each loop.

I'll post a simple example and try to explain in a different way how a for-each loop works.

The for-each loop example:

public class ForEachTest {

    public static void main(String[] args) {

        List<String> list = new ArrayList<String>();
        list.add("111");
        list.add("222");

        for (String str : list) {
            System.out.println(str);
        }
    }
}

Then, if we use javap to decompile this class, we will get this bytecode sample:

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: new           #16                 // class java/util/ArrayList
         3: dup
         4: invokespecial #18                 // Method java/util/ArrayList."<init>":()V
         7: astore_1
         8: aload_1
         9: ldc           #19                 // String 111
        11: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        16: pop
        17: aload_1
        18: ldc           #27                 // String 222
        20: invokeinterface #21,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
        25: pop
        26: aload_1
        27: invokeinterface #29,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;

As we can see from the last line of the sample, the compiler will automatically convert the use of for-each keyword to the use of an Iterator at compile time. That may explain why object, which doesn't implement the Iterable interface, will throw an Exception when it tries to use the for-each loop.

极度宠爱 2024-07-11 08:59:22

代码是:

import java.util.ArrayList;
import java.util.List;

public class ForLoopDemo {

  public static void main(String[] args) {

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

    someList.add("monkey");
    someList.add("donkey");
    someList.add("skeleton key");

    // Iteration using For Each loop
    System.out.println("Iteration using a For Each loop:");
    for (String item : someList) {
      System.out.println(item);
    }

    // Iteration using a normal For loop
    System.out.println("\nIteration using normal For loop: ");
    for (int index = 0; index < someList.size(); index++) {
      System.out.println(someList.get(index));
    }
  }
}

The code would be:

import java.util.ArrayList;
import java.util.List;

public class ForLoopDemo {

  public static void main(String[] args) {

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

    someList.add("monkey");
    someList.add("donkey");
    someList.add("skeleton key");

    // Iteration using For Each loop
    System.out.println("Iteration using a For Each loop:");
    for (String item : someList) {
      System.out.println(item);
    }

    // Iteration using a normal For loop
    System.out.println("\nIteration using normal For loop: ");
    for (int index = 0; index < someList.size(); index++) {
      System.out.println(someList.get(index));
    }
  }
}
血之狂魔 2024-07-11 08:59:22

我认为这会起作用:

for (Iterator<String> i = someList.iterator(); i.hasNext(); ) {
   String x = i.next();
   System.out.println(x);
}

I think this will work:

for (Iterator<String> i = someList.iterator(); i.hasNext(); ) {
   String x = i.next();
   System.out.println(x);
}
同展鸳鸯锦 2024-07-11 08:59:22

这看起来很疯狂,但是嘿它有效

List<String> someList = new ArrayList<>(); //has content
someList.forEach(System.out::println);

这有效。 魔法

This looks crazy but hey it works

List<String> someList = new ArrayList<>(); //has content
someList.forEach(System.out::println);

This works. Magic

韬韬不绝 2024-07-11 08:59:22

Java for-each 习惯用法只能应用于*Iterable 类型的数组或对象。 这个习惯用法是隐式的,因为它真正由迭代器支持。 迭代器由程序员编程,通常使用整数索引或节点(取决于数据结构)来跟踪其位置。 从理论上讲,它比常规的 for 循环慢,至少对于数组和列表等“线性”结构来说是这样,但它提供了更好的抽象。

The Java for-each idiom can only be applied to arrays or objects of type *Iterable. This idiom is implicit as it truly backed by an Iterator. The Iterator is programmed by the programmer and often uses an integer index or a node (depending on the data structure) to keep track of its position. On paper it is slower than a regular for-loop, a least for "linear" structures like arrays and Lists but it provides greater abstraction.

悲念泪 2024-07-11 08:59:22
public static Boolean Add_Tag(int totalsize)
{
    List<String> fullst = new ArrayList<String>();
    for(int k=0; k<totalsize; k++)
    {
        fullst.addAll();
    }
}
public static Boolean Add_Tag(int totalsize)
{
    List<String> fullst = new ArrayList<String>();
    for(int k=0; k<totalsize; k++)
    {
        fullst.addAll();
    }
}
电影里的梦 2024-07-11 08:59:22

正如许多其他答案正确指出的那样,foreach循环只是相同旧for循环的语法糖,编译器将其转换为相同旧for< /em> 循环。

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

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

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

因此,让我们删除语法糖

为了回答这个问题,我创建了一个文件并为每个文件编写了两个版本的 ,一个使用 array,另一个使用 array一个列表。 我的 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);
            }
        }
    }
}

您可以看到,与其他语法糖(自动装箱)一起,foreach 循环已更改为简单循环。

As many of other answers correctly state, the for each loop is just syntactic sugar over the same old for loop and the compiler translates it to the same old for loop.

javac (OpenJDK) has a switch, -XD-printflat, which generates a Java file with all the syntactic sugar removed. The complete command looks like this:

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

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

So let’s remove the syntactical sugar

To answer this question, I created a file and wrote two versions of for each, one with array and another with a list. My Java file looked like this:

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

When I compiled this file with above switch, I got the following output.

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

You can see that along with the other syntactic sugar (Autoboxing), for each loops got changed to simple loops.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文