検索

ホームページ  >  に質問  >  本文

问一个JAVA代码性能问题

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

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

迷茫迷茫2805日前841

全員に返信(3)返信します

  • 伊谢尔伦

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

     HashMap map1 = 新しい HashMap<>();
        マップ<文字列, 文字列> map2 = 新しい HashMap<>();
        map1.put("a", "b");
        map2.put("a", "b");
        

    =>

    16 aload_1 [map1]
    17 ldc <文字列 "a"> [160]
    19 ldc <文字列 "b"> [162]
    21 invokevirtual java.util.HashMap.put(java.lang.Object, java.lang.Object) : java.lang.Object [164]
    24ポップ
    25 aload_2 [マップ2]
    26 ldc <文字列 "a"> [160]
    28 ldc <文字列 "b"> [162]
    30 invokeinterface java.util.Map.put(java.lang.Object, java.lang.Object) : java.lang.Object [168] [nargs: 3]
    

    ここの調査中、http://bobah.net/book/export/html/55
    invokeinterface 可能性低い 38%

    http://stackoverflow.com/questions/1504633/what-is-the-point-of-invokeinterface
    ここ有解释

    返事
    0
  • 阿神

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

    この質問に対する一般的な答えは、「ほぼ同じで、違いはありません」です。
    より極端な答えは、「2 のパフォーマンスは 1 よりわずかに優れています」です。

    次のコード:

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

    バイトコードにコンパイルした後の対応する命令は次のとおりです。

    0: new #16 // クラス java/util/HashMap
             3: ダップ
             4: invokespecial #18 // メソッド java/util/HashMap."":()V
             7:astore_1
             8: ロード_1
             9: ldc #19 // 文字列テスト
            11: ldc #19 // 文字列テスト
            13: invokevirtual #21 // メソッド java/util/HashMap.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
            16:ポップ
            17: aload_1
            18: ldc #19 // 文字列テスト
            20: invokevirtual #25 // メソッド java/util/HashMap.get:(Ljava/lang/Object;)Ljava/lang/Object;
            23:ポップ
            24: 新しい #16 // クラス java/util/HashMap
            27:ダップ
            28: invokespecial #18 // メソッド java/util/HashMap."":()V
            31: アストア_2
            32: ロード_2
            33: ldc #19 // 文字列テスト
            35: ldc #19 // 文字列テスト
            37: invokeinterface #29, 3 // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
            42:ポップ
            43: ロード_2
            44: ldc #19 // 文字列テスト
            46: invokeinterface #32, 2 // InterfaceMethod java/util/Map.get:(Ljava/lang/Object;)Ljava/lang/Object;
            51:ポップ
            52: リターン

    ケース 1 のマップの put/get 操作は invokevirtual 命令を使用して完了し、ケース 2 のマップの put/get 操作は < を使用して完了することがわかります。 code>invokeinterface コマンドが完了しました。

    実装に関しては、invokevirtual のパフォーマンスが invokeinterface よりわずかに優れているため、どちらのパフォーマンスが優れているかと言えば、2 です。

    最後に、注意事項として、Java プログラミングのプロセスでは、すべての jvm 命令は、それが invokedynamic であっても、ほぼ同じ一定レベルの時間オーバーヘッドがあると見なされるべきです。上位レベルのアルゴリズムを提供し、ロジックの最適化は統合された干渉のない視点をもたらします。
    JVM 命令をエッジの効いた方法で選択するために Java コードの記述方法を変更するのは非合理であり、その結論も不安定です- jvm がアップグレードされると変更される可能性があります。さらに、この「パフォーマンスの向上」によってもたらされるコードの変更は可読性と保守性の低下につながり、利益に値しません

    返事
    0
  • ringa_lee

    ringa_lee2017-04-17 14:47:38

    運用方法によれば、2 のパフォーマンスは 1 よりも優れています。

    返事
    0
  • キャンセル返事