2

I saw the following code and was wondering the intent of the coder. Is it related performance of autoboxing?

map.put("doesntMatter", Boolean.TRUE);

He could have done:

map.put("doesntMatter", true);

Any benefits of doing the first?

Raedwald
  • 46,613
  • 43
  • 151
  • 237
SurenNihalani
  • 1,398
  • 2
  • 15
  • 28
  • I'd say the compiler is smart enough so any of those will have the same effect. - We could do the test, though. – acdcjunior Jun 21 '13 at 18:22
  • Either what @acdcjunior said, or at runtime, the JIT will figure this out. So, no real interest ultimately. – fge Jun 21 '13 at 18:23
  • 1
    Just checked via Oracles's `javap`, and, good or no good, `map.put("doesntMatter", true)` is converted to `map.put("doesntMatter", Boolean.valueOf(1))`. So it generates one extra instruction (that pushes `1` onto the stack before calling the `valueOf` method) and uses a `invokestatic` instead of a `getstatic` (used in the first statement). I is hard to draw any conclusions from this (because the JIT will come into play when the real time comes; and different compilers generate different bytecodes), but what I just described is what actually happens with Oracle´s `javac` and `javap`. – acdcjunior Jun 21 '13 at 18:38
  • Not really a duplicate question, as this question is asking specifically about the context where a `Boolean`, rather than a `boolean`, is needed. – Raedwald Jun 21 '13 at 18:45

2 Answers2

5

I've written an example:

public class Demo {

    Map<String, Boolean> map = new HashMap<>();

    void primitive() {
        map.put("a", true);
    }

    void object() {
        map.put("b", Boolean.TRUE);
    }
}

look at the bytecode of primitive()

 0 aload_0
 1 getfield #17 <Demo/map Ljava/util/Map;>
 4 ldc #24 <a>
 6 iconst_1
 7 invokestatic #26 <java/lang/Boolean/valueOf(Z)Ljava/lang/Boolean;>
10 invokeinterface #32 <java/util/Map/put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;> count 3
15 pop
16 return

and the the bytecode of object()

 0 aload_0
 1 getfield #17 <Demo/map Ljava/util/Map;>
 4 ldc #39 <b>
 6 getstatic #41 <java/lang/Boolean/TRUE Ljava/lang/Boolean;>
 9 invokeinterface #32 <java/util/Map/put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;> count 3
14 pop
15 return

Conclusion:

when using the primitive, there is an extra step calling Boolean.valueOf(), but if you run that piece of code often, the JIT compiler will do it's job and optimize it away.

jlordo
  • 37,490
  • 6
  • 58
  • 83
1

The benefits are not in execution time, as this little test code shows :

Results :

Time with primitives : 3334779619
Time with Object : 4092034749
Time with primitives : 3670851766
Time with Object : 2748035018
Time with Object : 3738916372
Time with primitives : 2975196722
Time with Object : 2514328271
Time with primitives : 2588980283
Time with Object : 2696162369
Time with primitives : 2615258656
Time with primitives : 2633824223
Time with Object : 2489779261

Code :

import java.util.HashMap;
import java.util.Map;

import javax.swing.JOptionPane;

public class Test
{
  public static void main(String[] args) {
    JOptionPane.showMessageDialog(null, "Start");

    createWithPrimitive();
    createWithObject();
    createWithPrimitive();
    createWithObject();
    createWithObject();
    createWithPrimitive();
    createWithObject();
    createWithPrimitive();
    createWithObject();
    createWithPrimitive();
    createWithPrimitive();
    createWithObject();

    System.exit(0);
  }

  private static void createWithObject() {
    long time = System.nanoTime();
    Map<Integer, Boolean> testMap = new HashMap<Integer, Boolean>();
    for (int i = 1; i <= 10000000; i++) {
      if (i % 2 == 0) {
        testMap.put(i, Boolean.TRUE);
      } else {
        testMap.put(i, Boolean.FALSE);
      }
    }

    System.out.println("Time with Object : " + (System.nanoTime() - time));
  }

  private static void createWithPrimitive() {
    long time = System.nanoTime();
    Map<Integer, Boolean> testMap = new HashMap<Integer, Boolean>();
    for (int i = 1; i <= 10000000; i++) {
      if (i % 2 == 0) {
        testMap.put(i, true);
      } else {
        testMap.put(i, false);
      }
    }

    System.out.println("Time with primitives : " + (System.nanoTime() - time));
  }
}
Jonathan Drapeau
  • 2,610
  • 2
  • 26
  • 32
  • What if you put `for (int i = 1; i <= 10000000; i++) testMap.put(i, isEven(i));` - I guess the compiler won't be able to optimize that – Hertzu Feb 17 '22 at 20:30