开发者

Weird java for-each behavior when swapping variables

With the follow code, I expect four elements, but get only three. Clearly I'm doing something crazy silly.

import java.util.HashSet;

import java.util.Set;

public class MyTest {
    public static void main(String[] args) {
        String[] myStrings = new String[] { "a", "b" };

        Set<String> set = new HashSet<String>();
        for (String x : myStrings) {
  开发者_运维技巧          for (String y : myStrings) {
                String temp = x;
                x = y;
                y = temp;

                set.add(x + y);
            }
        }

        System.out.println(set);
    }
}

result:

[ba, aa, ab]


Sets don't allow duplicates, and you're adding 'ba' twice. Your loop control if confusing, but here's the simplified trace, with rvalues expanded.

x = "a"

y = "a"
temp = "a"
x = "a"
y = "a"
add("aa")

y = "b"
temp = "a"
x = "b"
y = "a"
add("ba")

x = "b"

y = "a"
temp = "b"
x = "a"
y = "b"
add("ab")

y = "b"
temp = "a"
x = "b"
y = "a"
add("ba")


You are modifying the variable of the outer loop each time you run through the inner loop. So x can become corrupted.

In particular the penultimate execution of the body assigns 'a' to x. Next time round the loop we miss out on "bb", instead getting a duplicat "ab".

Using final is quite handy.


Playing with loop variables is the issue.

Do this:

    Set<String> set = new HashSet<String>();
    for (String x : myStrings) {
        for (String y : myStrings) {
            String temp = x;
            x = y;
            y = temp;
            System.out.println(x+y);
            set.add(x + y);
        }
    }

You will see you are adding ab twice, which in a Set means overwriting. Then change the loop to use something other than loop variables like:

    Set<String> set = new HashSet<String>();
    for (String a : myStrings) {
        for (String b : myStrings) {
            String x = a;
            String y = b;
            String temp = x;
            x = y;
            y = temp;
            System.out.println(x+y);
            set.add(x + y);
        }
    }

And you will get all 4 things you want. I have to do some more reading about how traversing an array in the way you have done works, but that is clearly the culprit.


You're changing the outer loop variable, so the output is unexpectedly missing "bb".


for (String x : myStrings) {
    for (String y : myStrings) {
        String temp = x;
        x = y;
        y = temp;

        set.add(x + y);
    }
}

Why are you assigning things to x and y when they are both for loop variables? If you wish to loop through x and y independently, get rid of those 3 lines to swap x and y. You are modifying the variables in a way that is probably different than you expect.


Maybe it's because you're putting the resulting strings into a hash set, which doesn't preserve order. Try with a linked hash set.


The problem is simple -- where is "bb" in the output. It should generate 4 strings.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜