简体   繁体   English

为什么我的递归Java方法中的字段会更改?

[英]Why does the field in my recursive Java method change?

I have been learning Java for about a month now and have learned a lot by reading others' questions (and answers) on this site. 我已经学习Java大约一个月了,通过阅读本网站上其他人的问题(和答案),我学到了很多东西。 I don't think that this has been asked before (but if it has, I would appreciate a pointer ...) 我认为以前没有问过这个问题(但是如果有的话,我将不胜感激指针...)

In the code below, pretty much everything which is not indented are error-checking printouts, so the code is quite a bit shorter than it seems. 在下面的代码中,几乎所有未缩进的内容都是错误检查打印输出,因此代码比看起来短了很多。 The code is my attempt at using recursion to list all the ways that numBalls balls can be placed in numBins bins. 该代码是我尝试使用递归列出numBalls球可以放在numBins箱中的所有方式的尝试。

Main question: The method works fine for numBins < 3. As soon as numBins is set to 3, the endList field (in the recursive call) has more than 1 "row", and as soon as j hits 1 in the loop directly below, the indexList field gets changed. 主要问题:该方法适用于numBins <3。当numBins设置为3时, endList字段(在递归调用中)具有1个以上的“行”,并且j在下面的直接循环中击中1 , indexList字段将更改。 For example, calling testList = distributeBallsInBins(1,3,""); 例如, calling testList = distributeBallsInBins(1,3,""); in the main method (as it is configured), leads to a change in the second row of indexList from {0 1 0} to {0 0 1} (as shown in the output) , but I cannot see how/why it has changed when all I have done is moved to the next j (ie from j=0 to j=1) 在main方法(按配置)中,导致indexList的第二行从{0 1 0}更改为{0 0 1}(如输出所示),但我看不到它如何/为什么我完成的所有操作都移到下一个j时发生了更改(即从j = 0到j = 1)

Secondary question: I have replaced all the Integer[] occurrences with int[] and there seems to be no difference. 第二个问题:我用int[]替换了所有Integer[]出现的地方,似乎没有什么区别。 Should there be? 应该有吗? I guess I need to read more on the difference between primitive and reference types, but I don't really understand the difference here. 我想我需要阅读更多有关原始类型和引用类型之间的区别的信息,但是我真的不太了解这里的区别。

Thank you in advance, Mike 预先谢谢迈克

import java.util.*;

public class testRecursion
{
     public static List<Integer[]> distributeBallsInBins(int numBalls, int numBins, String tmpTxt)
    {
        if (numBins==1)
        {
            List<Integer[]> lastList = new ArrayList<Integer[]>();
            lastList.add((new Integer[] {numBalls}));
            return lastList;
        }
        else if (numBalls==0)
        {
            List<Integer[]> lastList = new ArrayList<Integer[]>();
            Integer[] tmpNum = new Integer[numBins];
            for (int k=0; k<numBins; k++)
                tmpNum[k] = 0;
            lastList.add(tmpNum);
            return lastList;
        }
        else
        {
            List<Integer[]> indexList = new ArrayList<Integer[]>();
            for (int i=numBalls; i>=0; i--)
            {
                Integer[] newLine = new Integer[numBins];
                newLine[0] = i;
                List<Integer[]> endList = distributeBallsInBins((numBalls-i), (numBins-1), (tmpTxt + "    "));
                for (int j=0; j<endList.size(); j++)
                {
                    Integer[] newLineEnd = endList.get(j);
                    for (int k=0; k<numBins-1; k++)
                        newLine[k+1] = newLineEnd[k]; 
                    indexList.add(newLine);
                }
            }
        return indexList;
        }
    }

    public static void main(String[] args)
    {
        List<Integer[]> testList = distributeBallsInBins(1,3,"");
    }
}

Your problem is, that you are always modifying and inserting the same array into your result list. 您的问题是,您总是在修改相同的数组并将其插入到结果列表中。 Since Java handles all objects per reference, you'll end up with a list containing the same array over and over again. 由于Java处理每个引用的所有对象,因此最终将得到一个包含相同数组的列表。

So you need to either clone the array before adding it to the list: 因此,您需要先clone阵列,然后再将其添加到列表中:

indexList.add(newLine.clone());

Or create the newLine array new every time you iterate your j -loop: 或在每次循环j -loop时创建new的newLine数组:

for (int j = 0; j < endList.size(); j++) {
    Integer[] newLine = new Integer[numBins];
    newLine[0] = i;
    Integer[] newLineEnd = endList.get(j);
    for (int k = 0; k < numBins - 1; k++)
        newLine[k + 1] = newLineEnd[k];
    indexList.add(newLine);
} // next j

Regarding Objects versus primitives: Changing to int[] did not help because the array itself is still an Object and thus passed by reference. 关于对象与基元:更改为int[]并没有帮助,因为array本身仍然是Object ,因此通过引用传递。

just replace this line 只需替换此行

indexList.add(newLine);

with Line 带线

indexList.add(newLine.clone());

this will work...... this will pass new array rather than pass the reference of old array....... 这将工作......这将通过新数组而不是通过旧数组的引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM