Java HashMapは実践を遍歴し、異なる方法の性能を見てみましょう.

4375 ワード

元の記憶では、Java HashMap遍歴は、for eachやiteratorにほかならないが、遍歴時の性能がどうなのか、メリットとデメリットがどうなのかは、一般的には分からない.このような基礎的な問題に対して、王二(Javaプログラミング6年、幸い私の方向はプログラミングではない)にとって、私は耻ずかしそうに言及したが、事実は私がまだ「シリコンステップを積まなければならない」ことを証明した.
①メソッド1、iterator反復keysおよびvaluesの検索
この方法は私が最も頻繁に使用しているもので、一つもありません.詳細は以下のコードを参照してください.
Map map = new HashMap();

addMap(map);

long t1 = System.currentTimeMillis();
Iterator keys = map.keySet().iterator();

while (keys.hasNext()) {
    Integer key = keys.next();
    Integer value = map.get(key);

    keys.remove();
}

long t2 = System.currentTimeMillis();
System.out.println("map.keySet().iterator()  :" + (t2 - t1));
以前の私から見れば、この方法はかなり簡潔で、iteratorを通じてkeysを遍歴し、keyを通じてmapから対応するvalueを取得し、非常に接地しているようだ.しかし、弊害は
それはより遅く、より低効率であり、keyによってvalue値を得るのに時間がかかる(この方法は、mapインタフェースを実現するすべてのmapにおいて、方法1より20%〜200%遅い).FindBugsをインストールすると、低効率な反復であることが検出され、警告されます.この方法は避けるべきだ.
このメッセージを見て、私は少し唐突だと思います.どうして一番好きなmap遍歴方式がこんなにlowなのか、がっかりしました.後でかかるパフォーマンス時間を統計して、しばらく注目してください.
②方法2、Iterator反復Entry
この方法は以前はほとんど使わなかったが、方法2には重要な利点がある.
  • は、iteratorによってmapの要素を削除することができる.方法は同じです.
  • は性能に優れている.
  • Map map = new HashMap();
    addMap(map);
    
    long t3 = System.currentTimeMillis();
    Iterator> entrys = map.entrySet().iterator();
    
    while (entrys.hasNext()) {
        Entry entry = entrys.next();
        Integer key = entry.getKey();
        Integer value = entry.getValue();
    
        entrys.remove();
    }
    
    long t4 = System.currentTimeMillis();
    System.out.println(" map.entrySet().iterator()  :" + (t4 - t3));
    「map.entrySet().iterator()」でmapのentryオブジェクトを取得し、getKey、getValueでkeyとvalueを取得する価値があり、非常に率直で実用的です.
    ③方法3:For-EAch反復keysとvalues
    for eachの限界は異なるremove mapの要素ですが、mapを巡るのはとてもいいです.
    Map map = new HashMap();
    addMap(map);
    
    long t5 = System.currentTimeMillis();
    for (Integer key : map.keySet()) {
    }
    
    for (Integer value : map.values()) {
    }
    long t6 = System.currentTimeMillis();
    System.out.println("for each map.keySet()、map.values()  :" + (t6 - t5));
    しかし、ここで、王二はstackoverflowで述べたように、この方法は次の4つ目の方法「For-EAch反復entries」よりも性能が良い(約10%速い)と言いますが、私の実践ではそうではありません.この方法は逆に4つ目の「For-EAch反復entries」よりずっと遅いです.
    ④方法四:For-EAch反復entries
    Map map = new HashMap();
    addMap(map);
    
    long t7 = System.currentTimeMillis();
    for (Entry entry : map.entrySet()) {
        Integer key = entry.getKey();
        Integer value = entry.getValue();
    }
    long t8 = System.currentTimeMillis();
    System.out.println("for each map.entrySet()  :" + (t8 - t7));
    この方法はあまり紹介しません.
    ⑤性能スケジュール
    オーダー
    iterator反復keysとvaluesの検索
    Iterator反復Entry
    For-EAch反復keysとvalues
    For-EAch反復entries
    1
    所要時間:37
    所要時間:32
    所要時間:39
    所要時間:13
    2
    消費時間:29
    時間:18
    所要時間:32
    所要時間:15
    3
    所要時間:50
    時間:57
    所要時間:39
    消費時間:21
    4
    時間:47
    消費時間:31
    所要時間:39
    所要時間:14
    以下にまとめることができます.
  • keysを反復しvaluesを検索するのは非常に非効率で、最下位または第2の
  • にほぼランクインした.
  • For-EAch反復entriesのパフォーマンスは最適ですが、remove
  • は使用できません.
  • For-EAch反復keysとvaluesはFor-EAch反復entriesよりも性能(約10%)が速くなく、stackoverflow上のデータも
  • にすべて同調できない.
  • Iterator反復Entryのスキームは、性能に優れ、remove
  • を使用するのに最適であることは明らかである.
    参考記事
  • HashMap遍歴
  • 「沈黙王二のブログ」を読んでいただき、ありがとうございます.王二のブログがあなたに少し助けたり感動したりしたら、私(つまり王二)はあまり光栄ではありません.もしあなたがたまたま好きなら、伝言や私を信じてもいいです.これは私がもっと優秀な文章を作る最強の動力になります.