2017-02-21 13 views
2

どちらが高速ですか? foreachに一覧を追加するか、&をstreamに収集してマッピングする。dtのエンティティを変換するための高速な方法

//Solution 1 
List<Card> cards = mobileUserService.getCurrentUser().getUserCard(); 

final List<CardDTO> dtos = new ArrayList<>(cards.size()); 

cards.forEach(card -> dtos.add(cardTransformer.transform(card))); 

または

//Solution 2 
List<Card> cards = mobileUserService.getCurrentUser().getUserCard(); 

List<CardDTO> dtos = cards.stream() 
     .map(cardTransformer::transform) 
     .collect(Collectors.toList()); 

ベンチマーク:foreachがより速くなるようだ

ほとんどの場合。

テストコードバリアント1:

List<Card> cards = new ArrayList<>(); 
     for (int i = 0; i < count; i++) { 
     Card c = Card.createFakeCard(); 
     cards.add(c); 
    } 


    long startTime1 = System.nanoTime(); 
    //Solution 1 
    final List<CardDTO> dtos = new ArrayList<>(cards.size()); 
    cards.forEach(card -> dtos.add(cardTransformer.transform(card))); 
    long endTime1 = System.nanoTime(); 


    long startTime2 = System.nanoTime(); 
    //Solution 2 
    List<CardDTO> dtos2 = cards.stream() 
      .map(cardTransformer::transform) 
      .collect(Collectors.toList()); 

    long endTime2 = System.nanoTime(); 


    double runtime1 = (endTime1 - startTime1)/Math.pow(10, 6); 
    double runtime2 = (endTime2 - startTime2)/Math.pow(10, 6); 
    log.error("Number of elements: " + count + "\n" + 
      "Solution 1 " + 
      "Total time (ms): " + runtime1 + "\n" + 
      "Solution 2 " + 
      "Total time (ms): " + runtime2); 

結果バリアント1:

Number of elements: 1 
Solution 1 Total time (ms): 3.862259 
Solution 2 Total time (ms): 8.919641 
Number of elements: 1 
Solution 1 Total time (ms): 0.012556 
Solution 2 Total time (ms): 0.032712 
Number of elements: 1 
Solution 1 Total time (ms): 0.011565 
Solution 2 Total time (ms): 0.034363 
Number of elements: 2 
Solution 1 Total time (ms): 0.01619 
Solution 2 Total time (ms): 0.03965 
Number of elements: 10 
Solution 1 Total time (ms): 0.020486 
Solution 2 Total time (ms): 0.044607 
Number of elements: 100 
Solution 1 Total time (ms): 0.395842 
Solution 2 Total time (ms): 0.729233 
Number of elements: 1000 
Solution 1 Total time (ms): 0.276229 
Solution 2 Total time (ms): 0.37866 
Number of elements: 5000 
Solution 1 Total time (ms): 0.987951 
Solution 2 Total time (ms): 1.092693 
Number of elements: 10000 
Solution 1 Total time (ms): 2.701169 
Solution 2 Total time (ms): 3.287001 
Number of elements: 20000 
Solution 1 Total time (ms): 11.095115 
Solution 2 Total time (ms): 11.3046 
Number of elements: 50000 
Solution 1 Total time (ms): 4.339383 
Solution 2 Total time (ms): 6.235984 
Number of elements: 100000 
Solution 1 Total time (ms): 8.312332 
Solution 2 Total time (ms): 9.088485 

テストコードバリアント2:

List<Card> cards = new ArrayList<>(); 
     for (int i = 0; i < count; i++) { 
     Card c = Card.createFakeCard(); 
     cards.add(c); 
    } 



    long startTime2 = System.nanoTime(); 
    //Solution 2 
    List<CardDTO> dtos2 = cards.stream() 
      .map(cardTransformer::transform) 
      .collect(Collectors.toList()); 

    long endTime2 = System.nanoTime(); 


    long startTime1 = System.nanoTime(); 
    //Solution 1 
    final List<CardDTO> dtos = new ArrayList<>(cards.size()); 
    cards.forEach(card -> dtos.add(cardTransformer.transform(card))); 
    long endTime1 = System.nanoTime(); 

    double runtime1 = (endTime1 - startTime1)/Math.pow(10, 6); 
    double runtime2 = (endTime2 - startTime2)/Math.pow(10, 6); 
    log.error("Number of elements: " + count + "\n" + 
      "Solution 1 " + 
      "Total time (ms): " + runtime1 + "\n" + 
      "Solution 2 " + 
      "Total time (ms): " + runtime2); 

結果バリアント2:

Number of elements: 1 
Solution 1 Total time (ms): 1.672247 
Solution 2 Total time (ms): 9.868603 
Number of elements: 1 
Solution 1 Total time (ms): 0.005617 
Solution 2 Total time (ms): 0.043946 
Number of elements: 1 
Solution 1 Total time (ms): 0.005618 
Solution 2 Total time (ms): 0.040971 
Number of elements: 2 
Solution 1 Total time (ms): 0.006278 
Solution 2 Total time (ms): 0.041963 
Number of elements: 10 
Solution 1 Total time (ms): 0.011564 
Solution 2 Total time (ms): 0.045929 
Number of elements: 100 
Solution 1 Total time (ms): 0.065093 
Solution 2 Total time (ms): 0.121263 
Number of elements: 1000 
Solution 1 Total time (ms): 0.65555 
Solution 2 Total time (ms): 0.968456 
Number of elements: 5000 
Solution 1 Total time (ms): 0.779127 
Solution 2 Total time (ms): 1.244686 
Number of elements: 10000 
Solution 1 Total time (ms): 2.03769 
Solution 2 Total time (ms): 2.337048 
Number of elements: 20000 
Solution 1 Total time (ms): 6.12232 
Solution 2 Total time (ms): 6.038063 
Number of elements: 50000 
Solution 1 Total time (ms): 6.12232 
Solution 2 Total time (ms): 8.463334 
Number of elements: 100000 
Solution 1 Total time (ms): 16.468047 
Solution 2 Total time (ms): 17.86109 
+6

ベンチマークは何を表していますか? – Fildor

+4

もっと宣言的であれば 'map(card - > cardTransformer.transform(card))'を 'map(cardTransformer :: transform)'に置き換えることができます。 –

+0

大きな違いがあると思いますか?もしそうなら、なぜですか? – Kayaman

答えて

0

私はJVMがラムダを処理する方法について専門家ではありませんが、私は数ヶ月前に私自身の研究をいくつか行いました... あなたのストリームにある "lambdas"の数は鍵だと思います。

あなたがラムダを書くたびに、2つの主要な事が起こります:

  1. コンパイル時には、ラムダは、ホストクラスのプライベートメソッドとして抽出されます。 javap
  2. 実行時に、JVMはそのプライベートメソッドを呼び出すオブジェクトを作成します。 (そこより多くの楽しみではここにあるが、簡略化のために)

は、次に、あなたのコードでは、最初のケースはわずか1ラムダを持っていますが、第二は、ある時点でそのため2を持っている、JVMは、ワイヤになります2回目のケースでオブジェクトを2回作成してインスタンス化します。それはあなたの最初のコードが「より速い」ものです。

関連する問題