Foreach vs common for循环

Ale*_*sie 7 java foreach

我刚开始学习Java,我遇到的第一件事是foreach循环,不知道它的工作方式我做的第一件事是:

int[] array = new int [10];
for (int i: array){
    i = 1;
}
Run Code Online (Sandbox Code Playgroud)

显然无法分配1给数组的每个元素.然后我添加System.out.print(i);(后i = 1;)到循环的主体,看到屏幕的输出是,1111111111但因为i在循环内做一些事情是有效的,很可能i是数组的每个元素的副本,不是吗?(第一个问题)

如果上述情况属实,这并不意味着foreach循环比公共for循环要慢得多,因为它涉及制作数组中每个元素的副本?或者既然Java没有指针和指针算术,oprator[]可能会以其他一些"糟糕"的方式设计复制每个元素实际上更快?

如果上述假设为真,为什么人们会使用明显较慢的foreach循环而不是共同的for循环呢?

简而言之:

  • i每个元素的副本array吗?如果不是那么呢?

  • foreach循环不是比普通循环慢吗?如果没有,那么operator[]设计的"糟糕"程度如何?

  • 除了在foreach循环中获胜的可读性之外别无其他吗?

Sot*_*lis 11

在代码中

for (int i: array){
Run Code Online (Sandbox Code Playgroud)

您声明一个变量i,在每个循环迭代中获取数组中下一个元素的值,它不是对该元素的引用.

i = 1;
Run Code Online (Sandbox Code Playgroud)

您为变量赋值,而不是为数组中的元素赋值.

您不能直接使用foreach循环设置数组元素的值.使用正常for循环

for (int i = 0; i < array.length; i++) {
    array[i] = ...; // some value
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,您使用声明的变量i作为数组中元素的索引.

array[i] 
Run Code Online (Sandbox Code Playgroud)

正在访问您可以修改其值的元素本身.


Ans显然无法为数组的每个元素分配1.我添加了System.out.print(i); 到循环的主体,看到屏幕的输出是1111111111但是因为在循环内部做一些事情是有效的,我很可能是数组中每个元素的副本,不是吗?(第一个问题)

你必须把它放在System.out.print(i)后面i = 1,否则你会得到0000000.

如果上述情况属实,那么这并不意味着foreach循环比公共for循环要慢得多,因为它涉及复制数组的每个元素?或者由于Java没有指针和指针算术,oprator []可能会以其他"严重"的方式设计,复制每个元素实际上更快?

看看这里 foreach循环是如何工作的.对于数组,

for (int i: array){
    i = 1;
}
Run Code Online (Sandbox Code Playgroud)

相当于

for (int index = 0; index < array.length; index++) {
    int i = array[index];
    i = 1;
}
Run Code Online (Sandbox Code Playgroud)

所以它并不慢.你在堆栈上做了一个更原始的创建.

这取决于实施.对于数组,它不会以任何方式变慢.它只是用于不同的目的.

为什么人们会使用明显较慢的foreach循环而不是常见的forloop?

一个原因是可读性.另一种是当你不关心更改数组的元素引用时,而是使用当前引用.

以参考类型为例

public class Foo {
    public int a;
}

Foo[] array = new Foo[3];
for (int i = 0; i < array.length; i++) {
    array[i] = new Foo();
    array[i].a = i * 17;
}

for (Foo foo : array) {
    foo.a = 0; // sets the value of `a` in each Foo object
    foo = new Foo(); // create new Foo object, but doesn't replace the one in the array
}
Run Code Online (Sandbox Code Playgroud)

对于原始类型,这样的东西不起作用.

for (int index = 0; index < array.length; index++) { 
    int i = array[index];
    i = 1; // doesn't change array[index]
}
Run Code Online (Sandbox Code Playgroud)


JNL*_*JNL 7

来自Joshua Bloch的Effective Java中的第46项:

在1.5版中引入的for-each循环通过完全隐藏迭代器或索引变量来消除混乱和错误的机会.由此产生的习语同样适用于集合和数组:

// The preferred idiom for iterating over collections and arrays
for (Element e : elements) {
    doSomething(e);
}
Run Code Online (Sandbox Code Playgroud)

当您看到冒号(:)时,将其读作"in".因此,上面的循环读作"对于元素中的每个元素e".请注意,使用for-each循环没有性能损失,即使对于数组也是如此.实际上,在某些情况下,它可能比普通的for循环提供轻微的性能优势,因为它只计算一次数组索引的限制.虽然您可以手动执行此操作(第45项),但程序员并不总是这样做.

好处

  1. 可读性
  2. 它增加了抽象级别 - 而不是必须表达如何围绕列表或数组(使用索引或迭代器)循环的低级细节,开发人员只是声明他们想要循环而语言负责其余部分.

坏处:

无法访问索引或删除项目.

总结一下,

增强的for循环提供

  1. 一个简洁的高级语法循环遍历列表或数组

    1.1提高清晰度

    1.2可读性.

    但是,它错过了:允许访问索引循环或删除项目.