Java 8 Lambda対LambdaJ対Guava対反復アプローチ

2013年半ばに、Java 8はラムダ式の実装を発表しました。 ラムダ式は、関数型プログラミングスタイルを適用するための十分な範囲を提供します。 ライブラリーLambdaJおよびGuavaを使用して、JDK 7、6または5で真の機能スタイルを今日使用できます。

反復的 ラムダジ 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(); } }));
      
      







参照資料







更新する



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



All Articles