web-dev-qa-db-ja.com

ConcurrentHashMap.newKeySet()とCollections.newSetFromMap()

Java 8は、同時Set実装を取得するための新しい方法を導入しました

// Pre-Java-8 way to create a concurrent set
Set<String> oldStyle = Collections.newSetFromMap(new ConcurrentHashMap<>());
// New method in Java 8
Set<String> newStyle = ConcurrentHashMap.newKeySet();

新しい方法を好む理由はありますか?

長所/短所はありますか?

16
turbanoff

ConcurrentHashMap.newKeySet()は、単一レベルの間接参照を削除するため、いくらか効率的です。 Collections.newSetFromMap(map)は主に操作をmap.keySet()にリダイレクトすることに基づいていますが、ConcurrentHashMap.newKeySet()map.keySet()自体に非常に近いです(追加サポートがある場合のみ) 。

機能性に関しては、違いは見られません。

8
Tagir Valeev

ConcurrentHashMap.newKeySet()は、Collections.newSetFromMap(new ConcurrentHashMap<>())よりもはるかに幅広い機能の一部にすぎません。

この例を見ると、違いが明らかになります。

_Set<String> set=new ConcurrentHashMap<String,String>().keySet("hello");
_

_Boolean.TRUE_にマッピングする代わりに、Setに新しい値を追加するときに値_"hello"_を追加するようになりました。

そのため、返されるSetsのタイプは _ConcurrentHashMap.KeySetView_ です。このタイプには、 バッキングマップを要求する および 新しいキーを追加するときに使用される値 の追加メソッドがあります。


したがって、ConcurrentHashMap.newKeySet()Collections.newSetFromMap(new ConcurrentHashMap<>())と同じように見えますが、前者は機能の一部であるため、後者は後でマップを使用しないように指示するという意味上の違いがあります。マップと対話するように設計されています。

_Collections.newSetFromMap_ を参照してください:

指定されたマップは、このメソッドが呼び出された時点では空である必要があり、このメソッドが戻った直後にアクセスしないでください。

実際、_Collections.newSetFromMap_が付加価値に_Boolean.TRUE_を使用することさえ指定されていません。とにかくそれを扱うべきではありません…


_ConcurrentHashMap.KeySetView_を明示的に要求するコードにSetを渡したい場合にも役立つことがあります。


コンパイル時の型Setのみを使用して結果を使用している場合でも、そのSetを受信するコードがinstanceof/typeキャストを使用して検出する可能性があります。 ConcurrentHashMap.newKeySet()の結果はConcurrentHashMapによって裏付けられていますが、_Collections.newSetFromMap_の結果はわかりません。一方で、それはまた、コードがそのようにバッキングマップで意図しないことをすることを可能にします…

14
Holger