2016-04-20 8 views
0

たとえば、特定のComparatorでコレクションをソートしようとしています。パフォーマンスの観点から見ると、sorted()節で定義されたコンパレータを不幸なインスタンスとして扱うか、または一度インスタンスを作成してsorted()節でcompareメソッドを呼び出す方が良いでしょうか?本質的にはストリーム内の匿名ソートとしてのコンパレータ

、より良いものです:

  1. myCollection.stream().sorted(
        new Comparator<String>(){ 
         public int compare(String a, String b){ 
          //code 
         } 
        }) 
    
  2. Comparator<String> comp = new MyCustomComparator<>(); 
    myCollection.stream().sorted(comp::compare) 
    

注:文法や、問題の値を比較どちらも - 私はJVMの初期化に十分にスマートであるかどうかを概念的に知りたいです私の匿名コンパレータは1回だけ(ケース1)、1つのメソッドを再利用し続けるか、新しいインスタンスを作成し続けます(ケース2を選択します)。

+0

これらの2つのアプローチは同じである必要があります。 – Dongqing

答えて

1

匿名クラスの新しいインスタンスをnewを使用して式が評価されるたびに作成されます。あなたの最初の例で

  • は、新しいものは、あなたがsortedにそれを渡しているの文を実行するたびに作成されます。 comp変数が初期化されているところはどこでもあなたの2番目の例では

  • は、新しいものが作成されます。 compがインスタンスメンバーの場合は、それを所有するオブジェクトが作成されるたびに作成されます。 compがメソッド内のローカル変数である場合、メソッドが呼び出されるたびに作成されます。

static、ステートレスおよび非キャプチャComparatorはいつもあなたが一度それを作成し、それを永遠に保つことができるので、最も効率的な方法になるだろう。 (たとえばString.CASE_INSENSITIVE_ORDERを参照してください。)

あなたが別の方法を使用してはならないわけではないこと。

のJava 8では、あなたは匿名クラスを超えるラムダを好む必要があります。非キャプチャラムダはキャッシュされ、一度しか作成できません。例えば、このプログラムは出力true

class Example { 
    public static void main(String[] args) { 
     System.out.println(comparator() == comparator()); 
    } 

    static Comparator<String> comparator() { 
     return (lhs, rhs) -> lhs.compareTo(rhs); 
    } 
} 

Ideone上の例。)

Javaでは、そこにいくつかの小さなオブジェクトを作成することを心配する必要はありません。なぜなら、避けられないこととガベージコレクタが最適化されているからです。大部分の時間、何かを行うための「最良の」方法も最も読みやすいです。


2番目の例では、メソッド参照を使用する必要はありません。メソッドに直接渡すことができます。

Comparator<String> comp = new MyCustomComparator<>(); 
myCollection.stream().sorted(comp)... 
+0

ありがとうございます。私は実際に彼らがどのように動作しているかという点で、匿名のインスタンスからのラムダの分離によって実際には驚いています。私はラムダの主な利点はちょうどよりコンパクトだと思った。明らかに、私はラムダについて何も知らない。 – dmitryvinn

+0

あなたの文章を正当化する必要があるかもしれません。 '表現が評価されるたびに匿名クラスの新しいインスタンスが作成されます。これは単に真実ではありません。簡単に確認できます。 'System.out.println(" this = "+ this)"というインスタンスイニシャライザブロックを匿名クラス 'new Comparator()...'に追加すると、そのインスタンスに対して作成された**インスタンスがちょうど**あることが示されます。ストリーム。 – SubOptimal

+0

@SubOptimal匿名クラス宣言は、式の評価時に新しいインスタンスを作成するクラスインスタンス作成式の一部です。 (これは 'new'を使った表現の一部です。)意味が実際に不明な場合は、私の答えを編集しました。 – Radiodef

0

両方のアプローチの実行時間は同じになります。

1st scenarioの場合、最初のJVMは、このオブジェクトの比較メソッドと割り当てられたスペースを匿名でカスタムコードでコンパイラーのインスタンスを作成します。したがって、最終的にオブジェクトは、ユーザのためのポインティング参照なしで作成され、メモリを割り当てられ、関数呼び出しが終了すると、オブジェクトはGCに登録されます。

2nd scenarioの場合、JVMはカスタムコードと割り当てられたスペースでコンパレータの新しいインスタンスを作成し、このオブジェクトを再び使用できるように別の変数に格納された参照を提供しますが、もう一度どこでもコードで。だから、GCが次回実行されるときには、変数の参照をスキャンし、GCedであるかどうかを調べなければなりません。

関連する問題