2016-11-30 9 views
4

MapをJava 8 StreamとインターフェイスでConcurrentHashMapに変換したい場合、2つのオプションがあります。Collectors.toConcurrentMapとCollectors.toMapサプライヤオプションを使用してMapをConcurrentHashMapに変換する違いは何ですか?

最初:

Map<Integer, String> mb = persons.stream() 
           .collect(Collectors.toMap(
              p -> p.age, 
              p -> p.name, 
              (name1, name2) -> name1+";"+name2, 
              ConcurrentHashMap::new)); 

そして第二:

1がより良い選択肢である
Map<Integer, String> mb1 = persons.stream() 
            .collect(Collectors.toConcurrentMap(
              p -> p.age, 
              p -> p.name)); 

?各オプションはいつ使うべきですか? toMapさんのJavadocから

答えて

4

パラレルストリームを扱う場合、それらの間に違いがあります。

toMap - >同時コレクタである(これは、その特性から分かる) - >

toConcurrentMap非並行コレクタです。

差がtoMapは、複数の中間結果を作成し、その後、toConcurrentMap単一結果、各スレッドが作成されている間、(例えば、コレクタのサプライヤーが複数回呼び出される)を一緒にマージすることです(そのようなコレクターのサプライヤは一度だけ呼び出されます)

これはなぜ重要ですか?これは、挿入順序を処理します(問題がある場合)。複数の中間結果をマージすることによって遭遇ために得られたマップの値を挿入する

toMap任意の順序で要素を収集する

toConcurrentMap(そのコレクタのサプライヤは、複数の時間ならびにコンバイナと呼ばれます)すべての要素を共通の結果コンテナ(この場合はConcurrentHashMap)にスローすることによって、未定義の状態になります。サプライヤは一度だけ、アキュムレータは何度も、コンバイナは決して呼び出されません。

私はシリアルストリームの場合はtoMap、パラレルストリームの場合はtoConcurrentMapを使用します。

+0

ストリームがパラレルでないと別のことが起こりますか?差異だけ私はCollectorImplに特性フラグを追加するだけで、そのフラグ(挿入順)に基づいて評価しますが、並列ストリームでない場合は両方のメソッドが同じ動作をしますが、HashMapはConcurrentHashMapを生成します。ストリームの振る舞いはそのパラレルの場合。 –

+2

@Bolzanoをパラレルストリームで使用すると、どちらの実装でもCombinerが呼び出されません。マージはアキュムレータ(あなたが持っている多くの要素と呼ばれ、サプライヤは一度だけ呼び出されます)で実行されます。だから、唯一の目に見える違いは、得られる結果です:HashMapとConcurrentHashMapです。 HashMap :: mergeを呼び出し、toConcurrentMapはConcurrentHashMap :: mergeを呼び出します。したがって、シリアル処理を行っている場合、なぜConcurrentHashMapが必要なのでしょうか? – Eugene

+0

私は@ KaranVermaに質問する必要があります。彼の質問では、彼は並列ストリームを使用していません。私はConcurrentHashMapの値を(スレッドセーフな操作のために)他の時間にキャッシュしようとしていると仮定しています。単純に: "この2コードブロックの違いは何ですか?" –

4

返さコレクターは、同時ではありません。並列ストリームパイプラインの場合、コンバイナ機能は、あるマップのキーを別のマップにマージすることによって動作します。これは高価な操作になります。検索結果をMapに挿入する必要がない場合は、toConcurrentMap(Function、Function)を使用すると、より良い並列パフォーマンスが得られる可能性があります。

toConcurrentMap結果をMapに挿入するのではなく、パフォーマンスが向上するはずです。

パラレルストリームを使用している場合は、挿入順序を気にしない場合は、toConcurrentMapを使用することをお勧めします。

関連する問題