Java:for / forEach通过int矩阵运行

时间:2014-05-14 14:35:47

标签: java loops foreach

这不是'怎么办......'问题,但是为什么我不能这样做'题。

显然我在这里错过了一些重要的事情(我猜是参考,我猜),要理解这个问题,如果有人能向我解释,那就太好了。

我确实找到了之前处理此问题的其他帖子,但没有人解释过它。

我想为int矩阵的每个元素分配新值。

我有一段这样的代码:

public static void main(String[] args)
{
    int[][] tileMatrix = new int[5][5];

    System.out.println("New Tile Values:");
    for ( int[] tileLine : tileMatrix)
    {
        for ( int tile : tileLine)
        {
            tile = (int) (Math.random() * 39);
            System.out.print(tile + "  ");
        }
        System.out.println("");
    }

    System.out.println("Check Values");
    for ( int[] tileLine : tileMatrix)
    {
        for ( int tile : tileLine)
        {
            System.out.print(tile + "  ");
        }
        System.out.println("");
    }
}

导致:

新瓷砖价值: 22 17 29 20 5
12 13 38 35 19
1 9 10 23 27
24 3 36 3 19
37 4 5 18 26
检查值 0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

显然,我无法改变这样的价值观。我无法确定在foreach循环中是否通常不可能,或者我是否只是做错了。我可以用正常的for循环解决我的问题,我知道,但为什么我必须这样做?

3 个答案:

答案 0 :(得分:8)

增强型for循环只会获取数组中元素的,并将它们存储在变量中。对于值,这意味着原语的副本或存储在数组中的引用值的副本。如果将新值重新分配给此变量,则只需修改此变量的值,而不是数组中的值。

这解释了为什么此for循环不起作用

for ( int tile : tileLine) {
    tile = (int) (Math.random() * 39);
    System.out.print(tile + "  ");
}

上面的for语句的行为如下:

for (int i = 0; i < tileLine.length; i++) {
    int tile = tileLine[i];
    //you modify the local variable tile, not the element in the array
    tile = (int) (Math.random() * 39);
    System.out.print(tile + "  ");
}

如果要修改数组中的值,则应直接在数组中修改该值:

for (int i = 0; i < tileLine.length; i++) {
    tileLine[i] = (int) (Math.random() * 39);
    System.out.print(tileLine[i] + "  ");
}

答案 1 :(得分:0)

我知道你提到过你并不想知道如何做某事,但你可能想看看JDK8 Arrays parallelPrefix method

答案 2 :(得分:0)

=仅影响您当前与

交互的变量

一个非常简单的例子说明了为什么你的循环不会改变存储在数组中的值

int a=5;
int b=a;
b=10;
System.out.println(a); //prints 5

你的代码显然比这更复杂,但内心却是一样的。数组中的每个值都被复制到一个变量中,然后操纵该变量。

for ( int[] tileLine : tileMatrix)
{
    for ( int tile : tileLine)
    {
        tile = (int) (Math.random() * 39); //<---tile is the same as b in my example
        System.out.print(tile + "  ");
    }
    System.out.println("");
}

引用对象的变量保存内存地址

您问为什么以下内容会影响基础2D数组

for ( int[] tileLine : tileMatrix){
    for (int i=0;i<tileLine.length;i++){
        tileLine[i] = (int) (Math.random() * 39);
    }
}

这是因为tileMatrix在其每个元素中都不包含1D数组,它包含内存地址(过度简化)。对于第120个内存区域,我将把内存地址称为#120

for ( int[] tileLine : tileMatrix){
    //tileLine is a memory address, perhaps #130, it is not an int[] itself
    //we only take a copy of the memory address, not a copy of the array itself 

    for (int i=0;i<tileLine.length;i++){
           //tileLine points to the piece of memory within the original 
           //array

           //tileLine[i] actually means get the array at memory address `#120` 
           //and put `(int) (Math.random() * 39);` in its i-th entry
           tileLine[i] = (int) (Math.random() * 39);
    }
}

因此,当您使用变量java(幕后)对其进行推理并得到真正的对象供您使用时,可以得出结论。

tileMatrix实际上是1D矩阵(假装是2D矩阵)。它可能包含以下内容

#120
#130
#1180
#2021
#2022

然后,当我们查看其中一个内存地址时,比如#120,我们发现它包含以下内容

1
5
5
1
4

所以你看我们是否有内存地址#120,无论我们在哪里,我们都指的是同一个地方。

这里的记忆模型不应该是准确的,只是在概念上有用,它在现实中比这更复杂