反復的 | ラムダジ | JDK 8ラムダ | グアバ | |
---|---|---|---|---|
すべてのブランドを印刷 | 79 | 472 * | 113 | 79 |
フェラーリのすべての販売を選択 | 25 | 146 | 44 | 31 |
最年少の人の買い物を見つける | 1,209 | 1,775 | 1,242 | 1,218 |
最も高価なセールを見つける | 8 | 123 | 55 | 72 |
両方が男性の場合の合計費用 | 23 | 973 * | 40 | 45 |
> 50,000で購入した最年少の年齢 | 1,521 | 2,576 * | 1,560 | 1,511 |
コストで売上を並べ替える | 350 | 1,187 | 473 | 453 |
車の元のコストを抽出する | 29日 | 61 | 31 | 31 |
ブランド別のインデックス車 | 57 | 70 | 89 | 415 |
買い手と売り手によるグループ販売 | 2,586 | 3,748 * | 2,862 | 1,601 |
最も購入した車を見つける | 744 | 1,023 * | クラッシュ | 1,435 |
Guavaはかなり広範なライブラリですが、そのコアはコレクションを操作するためのクラスで構成されており、ライブラリ自体はgoogle-collectionsから成長しています。 これらのクラスは、コレクションを操作するためのすべてを実装していますが、今日のJDKにはありません。 JDK 8をよく見ると、この新しい機能がすでにグアバにあるという感覚を常に得ています。 8番目のJavaの開発者は、グアバの経験に正確に依存している可能性があります。
LamdaJは、その名前にもかかわらず、ラムダ式を記述する機能を提供せず、むしろコレクションを操作するためのライブラリです。 コレクション内のアイテムをフィルタリング、変換、グループ化する機能を提供しますが、コードは非常にコンパクトで読みやすいです。 リフレクションとglibによって実装されており、パフォーマンスに利便性を払わなければならないことは明らかです。 LambdaJについてはすでにオタク誌に書いています
JDK 8では、ラムダ式はコンパイラレベルですでに実装されており、コンパイル段階でバイトコードに変換されるため、理論的にはこのようなコードのパフォーマンスは高くなります。
性能比較
JDK 8のラムダ式のパフォーマンスをLambdaJ、Guavaおよび通常の反復アプローチと実際に比較するために、LambdaJパフォーマンステストを行い、JDK 8およびGuavaで類似物を作成しました。
反復バージョンとLambdaJの最初のテストコードは変更されず、テストの名前は混乱を避けるために英語で保存されました。 テスト方法は次のとおりです。テストは100パスで実行され、各テストは100,000回実行され、各パスの合計実行時間が測定され、平均されます。
すべてのLambdaJテストがJRE 8で起動されたわけではなく、テーブル内でアスタリスクでマークされており、それらの結果はJRE 7で測定されました。
次の構成のコンピューターでテストを実行しました:Core i5 760 2.8 GHz 8 GB Win 7 sp-1 64 bit lambda-8-b45-windows-x64-24_jun_2012 jdk-7u4-windows-x64
その結果、反復コード、GuavaおよびJDKラムダが最良の結果をもたらしました。 彼らは非常に匹敵する結果を与えます。 一般に、ラムダ式は、反復と匿名クラスの非常に満足のいく置換を提供すると言えます。 JDK 8、グアバ、および反復アプローチの両方で非常に類似した結果が得られますが、LamdaJはほぼ一桁遅れており、その理由は反射の広範な使用にあると考えられます。
コレクションを操作する場合、GuavaおよびJDKラムダには1つの特性があることに注意してください。 多くの場合、コピーされたコレクションではなく、このビューの要素にアクセスするまで計算を延期するライブビューを返します。 したがって、テストでは、すべてのライブビューが明らかにコレクションに変換されました。 そうしないと、一部のテストではほぼ0ミリ秒の結果が得られます。 また、実生活では、どのアプローチを選択する必要もありません。たとえば、グアバはラムダ式と完全に結合します。
例
たとえば、各アプローチのソースコードは、 FindAgeOfYoungestWhoBoughtForMoreThan50000Testテストを見ることができるように見えます。 このテストでは、自動車販売店の販売リストが提供されます。このリストには、50,000を超えるお金で購入した最年少の購入者の年齢が表示されます。
反復アプローチ
int age = Integer.MAX_VALUE; for (final Sale sale : db.getSales()) { if (sale.getCost() > 50000.00) { final int buyerAge = sale.getBuyer().getAge(); if (buyerAge < age) { age = buyerAge; } } }
ラムダジ
final int age = Lambda.min(forEach(select(db.getSales(), having(on(Sale.class).getCost(), greaterThan(50000.00)))).getBuyer(), on(Person.class).getAge());
JDK 8ラムダ
final int age = Collections.min(db.getSales() .filter((Sale sale)->sale.getCost() > 50000.00) .<Integer>map((Sale sale)->sale.getBuyer().getAge()) .into(new ArrayList<Integer>()));
グアバ
final int age = Collections.min(transform(filter(db.getSales(), new Predicate<Sale>() { @Override public boolean apply(final Sale input) { return input.getCost() > 50000.00; } }), new Function<Sale, Integer>() { @Override public Integer apply(final Sale input) { return input.getBuyer().getAge(); } }));
参照資料
- Github.com/dmalch/lambda-comparisonテストソースコード
- LamdaJパフォーマンス分析code.google.com/p/lambdaj/wiki/PerformanceAnalysis
- ラムダなしのJDK 8をダウンロードjdk8.java.net/download.html
- ラムダ式jdk8.java.net/lambdaを含む JDK 8をダウンロードします
- LamdaJ code.google.com/p/lambdaj に関する Habriceの記事
更新する
TheShadeのアドバイスに基づいて、テスト手順に変更を加えました。加熱と信頼区間のカウントを追加しました。 結果は次のように変更されました。
反復的 | ラムダジ | JDK 8ラムダ | グアバ | |
---|---|---|---|---|
すべてのブランドを印刷 | 797.3 | 4,436.6 * | 1,073.2 | 912.1 |
フェラーリのすべての販売を選択 | 471.1 | 1,359.6 | 398.5 | 341.7 |
最年少の人の買い物を見つける | 12,102.4 | 17,436.2 | 12,267.4 | 12,144.5 |
最も高価なセールを見つける | 89.7 | 1,237.2 | 742.8 | 676.6 |
両方が男性の場合の合計費用 | 173.7 | 8,979.8 * | 372.7 | 394.5 |
> 50,000で購入した最年少の年齢 | 11,971.2 | 28,091.9 * | 11,672.1 | 15,975.6 |
コストで売上を並べ替える | 3,261 | 12,566.1 | 4,558.8 | 3,242.5 |
車の元のコストを抽出する | 292.1 | 628 | 322.8 | 213.1 |
ブランド別のインデックス車 | 548.8 | 672.1 | 867.8 | 4,324.6 |
買い手と売り手によるグループ販売 | 25,986.3 | 39,339.3 * | 28,109.2 | 15,068.9 |
最も購入した車を見つける | 7,378.3 | 9,317.2 * | クラッシュ | 10,002.1 |