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

2013年半ばに、Java 8はラムダ式の実装を発表しました。 ラムダ式は、関数型プログラミングスタイルを適用するための十分な範囲を提供します。 ライブラリーLambdaJおよびGuavaを使用して、JDK 7、6または5で真の機能スタイルを今日使用できます。
反復的ラムダジJDK 8ラムダグアバ
すべてのブランドを印刷79472 *11379
フェラーリのすべての販売を選択251464431
最年少の人の買い物を見つける1,2091,7751,2421,218
最も高価なセールを見つける81235572
両方が男性の場合の合計費用23973 *4045
> 50,000で購入した最年少の年齢1,5212,576 *1,5601,511
コストで売上を並べ替える3501,187473453
車の元のコストを抽出する29日613131
ブランド別のインデックス車577089415
買い手と売り手によるグループ販売2,5863,748 *2,8621,601
最も購入した車を見つける7441,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.34,436.6 *1,073.2912.1
フェラーリのすべての販売を選択471.11,359.6398.5341.7
最年少の人の買い物を見つける12,102.417,436.212,267.412,144.5
最も高価なセールを見つける89.71,237.2742.8676.6
両方が男性の場合の合計費用173.78,979.8 *372.7394.5
> 50,000で購入した最年少の年齢11,971.228,091.9 *11,672.115,975.6
コストで売上を並べ替える3,26112,566.14,558.83,242.5
車の元のコストを抽出する292.1628322.8213.1
ブランド別のインデックス車548.8672.1867.84,324.6
買い手と売り手によるグループ販売25,986.339,339.3 *28,109.215,068.9
最も購入した車を見つける7,378.39,317.2 *クラッシュ10,002.1

Source: https://habr.com/ru/post/J146718/


All Articles