Home  >  Q&A  >  body text

问一个JAVA代码性能问题

1: HashMap<String, String> test = new HashMap<>();
2: Map<String, String> test = new HashMap<>();

只进行put、get操作
请问1的性能会优于2吗?为什么?

迷茫迷茫2762 days ago795

reply all(3)I'll reply

  • 伊谢尔伦

    伊谢尔伦2017-04-17 14:47:38

        HashMap<String, String> map1 = new HashMap<>();
        Map<String, String> map2 = new HashMap<>();
        map1.put("a", "b");
        map2.put("a", "b");
        

    =>

    16  aload_1 [map1]
    17  ldc <String "a"> [160]
    19  ldc <String "b"> [162]
    21  invokevirtual java.util.HashMap.put(java.lang.Object, java.lang.Object) : java.lang.Object [164]
    24  pop
    25  aload_2 [map2]
    26  ldc <String "a"> [160]
    28  ldc <String "b"> [162]
    30  invokeinterface java.util.Map.put(java.lang.Object, java.lang.Object) : java.lang.Object [168] [nargs: 3]
    

    In the test here, http://bobah.net/book/export/html/55
    invokeinterface may be 38% slower

    http://stackoverflow.com/questions/1504633/what-is-the-point-of-invokeinterface
    Explanation here

    reply
    0
  • 阿神

    阿神2017-04-17 14:47:38

    For this question, the general answer is "about the same, there is no difference";
    The more extreme answer is "the performance of 2 is slightly better than 1";

    Code below:

    HashMap<String, String> m1 = new HashMap<>();
            m1.put("test", "test");
            m1.get("test");
    
            Map<String, String> m2 = new HashMap<>();
            m2.put("test", "test");
            m2.get("test");

    The corresponding instructions after being compiled into bytecode are:

    0: new           #16                 // class java/util/HashMap
             3: dup           
             4: invokespecial #18                 // Method java/util/HashMap."<init>":()V
             7: astore_1      
             8: aload_1       
             9: ldc           #19                 // String test
            11: ldc           #19                 // String test
            13: invokevirtual #21                 // Method java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
            16: pop           
            17: aload_1       
            18: ldc           #19                 // String test
            20: invokevirtual #25                 // Method java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
            23: pop           
            24: new           #16                 // class java/util/HashMap
            27: dup           
            28: invokespecial #18                 // Method java/util/HashMap."<init>":()V
            31: astore_2      
            32: aload_2       
            33: ldc           #19                 // String test
            35: ldc           #19                 // String test
            37: invokeinterface #29,  3           // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
            42: pop           
            43: aload_2       
            44: ldc           #19                 // String test
            46: invokeinterface #32,  2           // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
            51: pop           
            52: return

    It can be seen that the put/get operation of the map in case 1 is completed with the invokevirtual instruction;
    And the put/get operation of the map in case 2 is completed with the invokeinterface instruction;

    In terms of implementation, the performance of invokevirtual is slightly better than invokeinterface, so if we have to say who has better performance, it would be 2;

    Finally, as a reminder, in the process of java programming, any jvm instruction should be regarded as having almost the same constant-level time overhead, even if it is invokedynamic. Only in this way can we bring unity to our upper-level algorithms and logic optimization , non-interference perspective;
    It is irrational to change the way Java code is written in order to pick out jvm instructions in a sharp way, and its conclusion is also unstable - it may change with the upgrading of jvm, and for this purpose The code changes brought about by this kind of "performance improvement" lead to reduced readability and maintainability, which is not worth the gain

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 14:47:38

    Based on operational methodology, 2 performs better than 1

    reply
    0
  • Cancelreply