1
    @Test
    public void test(){
        Map<String, Integer> a = new HashMap<>();
        a.put("x", new Integer(0));
        Integer i = a.get("x");
        a.put("x", i++);
        i = a.get("x");
        a.put("x", i++);
        i = a.get("x");
        a.put("x", i++);
        System.err.println(i);
    }

The output of the above code is 1 and not 0. I cannot figure out why. Can someone explain whats going on? Some byte code optimizations by Java lead to this state?

user1615664
  • 591
  • 2
  • 11
  • 24

6 Answers6

4

Because i++ returns i before incrementing i. See my comments:

Map<String, Integer> a = new HashMap<>();
a.put("x", new Integer(0)); // x=0
Integer i = a.get("x");     // i=0
a.put("x", i++);            // x=0, i=1
i = a.get("x");             // i=0
a.put("x", i++);            // x=0, i=1
i = a.get("x");             // i=0
a.put("x", i++);            // x=0, i=1
System.err.println(i);

Here's the relevant part from the documentation of unary operators:

The increment/decrement operators can be applied before (prefix) or after (postfix) the operand. The code result++; and ++result; will both end in result being incremented by one.

The only difference is that the prefix version (++result) evaluates to the incremented value, whereas the postfix version (result++) evaluates to the original value.

If you are just performing a simple increment/decrement, it doesn't really matter which version you choose. But if you use this operator in part of a larger expression, the one that you choose may make a significant difference.

juzraai
  • 5,693
  • 8
  • 33
  • 47
1

Yes, it should be one. Last statement is a.put("x", i++); so you put the value 0 into your Map but then you increment i. If your last statement was i = a.get("x"); you would get 0.

Schidu Luca
  • 3,897
  • 1
  • 12
  • 27
1

You use post-increment, so the value of i is read first, then incremented.

 @Test
public void test(){
    Map<String, Integer> a = new HashMap<>();
    a.put("x", new Integer(0));
    Integer i = a.get("x"); // i is 0
    a.put("x", i++); // x = 0; then i increment
    i = a.get("x"); // i is reset to 0
    a.put("x", i++); // x = 0; then i increment
    i = a.get("x"); // i is reset to 0
    a.put("x", i++); // x = 0; then i increment
    System.err.println(i); // i == 1
}
QBrute
  • 4,405
  • 6
  • 34
  • 40
0

Explained inline:

@Test
public void test(){
    Map<String, Integer> a = new HashMap<>();
    a.put("x", new Integer(0)); // Store Integer(0)
    Integer i = a.get("x");     // Get it
    a.put("x", i++);            // Unbox it, rebox it, store it again (still 0); increment it afterward
    i = a.get("x");             // Same again
    a.put("x", i++);            // ...
    i = a.get("x");             // ...
    a.put("x", i++);            // Unbox it, rebox it, store it again (still 0); increment it afterward 
    System.err.println(i);      // Show it; contains the *incremented* value
}

Since the value stored is always 0, and you get it at the end and increment it, you end up with 1.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Lets go through this step by step:

    Integer i = a.get("x");

i is 0

    a.put("x", i++);

the "x" in the map doesnt change because you set it to i (=0) and increment after setting it.

    i = a.get("x");

Again i gets set to 0 since thats still whats stored in "x"

    a.put("x", i++);

Same thing as above, i gets set to one only after setting "x" to 0

    i = a.get("x");

i =0

    a.put("x", i++);

Now i is 1 and you print it

    System.err.println(i);
Claudio Brasser
  • 511
  • 3
  • 20
0

Your last statement increase i by 1 resulting i = 1.