私は次のパターンにうんざりしています:
value = map.get(key);
if (value == null) {
value = new Object();
map.put(key, value);
}
この例は、多次元構造を表すためにネストされたマップがある場合に記述される追加のコードの表面をほんの少しだけスクラッチします。
これを回避するためにどこかに何かが存在すると確信していますが、グーグルの努力は何の関連性ももたらしませんでした。提案はありますか?
の
Java.util.concurrent.ConcurrentMap
およびJava 8
Java.util.Map
持っている
putIfAbsent(K key, V value)
キーにマップされた値を返すか、キーに値がマップされていない場合は指定された値とnullを挿入します。
値の遅延評価が必要な場合は
computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
Java 8は Map にNiceメソッドを追加します: compute 、 computeIfPresent 、 computeIfAbsent
必要なものを実現するには:
Object existingOrCreated = map.computeIfAbsent(key, (k) -> new Object());
このパターンの問題は、get()
がnullを返す場合に使用する値を何らかの方法で定義する必要があることです。
確かにそこにはライブラリーがあり、IIRCはそれを行う新しいコレクションもいくつかありますが、残念ながら、それらがどれだったか覚えていません。
ただし、新しい値を作成する標準的な方法があれば、ユーティリティメソッドを自分で作成することもできます。このような何かが動作する可能性があります:
public static <K, V> V safeGet(K key, Map<K,V> map, Class<V> valueClass) throws /*add exceptions*/ {
V value = map.get(key);
if( value == null ) {
value = valueClass.newInstance();
map.put( key, value );
}
return value;
}
リフレクション例外をスローするか、メソッドでそれらを処理する必要があることに注意してください。さらに、これには引数なしのコンストラクターを提供するvalueClass
が必要です。あるいは、使用する必要があるデフォルト値を単に渡すこともできます。
Eclipse Collections から MutableMap およびgetIfAbsentPut()
を使用できます。キーにマップされます。
メソッド参照を使用して、新しいObject
を作成できます。
MutableMap<String, Object> map = Maps.mutable.empty();
Object value = map.getIfAbsentPut("key", Object::new);
または、新しいObject
を直接作成できます。
MutableMap<String, Object> map = Maps.mutable.empty();
Object value = map.getIfAbsentPut("key", new Object());
最初の例では、キーにマップされている値がない場合にのみオブジェクトが作成されます。
2番目の例では、オブジェクトは関係なく作成されます。
注:私はEclipse Collectionsの寄稿者です。
EDIT:下記の機能は廃止される予定であり、代わりに CacheBuilder を使用する必要があります。
Guavaライブラリには、「computing map」があります。 MapMaker.makeComputingMap(Function) 。
Map<String, Object> map = new MapMaker().makeComputingMap(
new Function<String, Object>() {
public String apply(Stringt) {
return new Object();
}
});
関数を数回必要とする場合は、それをユーティリティクラスに抽出し、次にこのようなマップを作成します(ここでMyFunctions.NEW_OBJECT
は静的なFunctionインスタンスです):
Map<String, Object> map = new MapMaker()
.makeComputingMap(MyFunctions.NEW_OBJECT);
問題全体を見ているわけではないかもしれませんが、継承または合成を使用してこの動作をMapオブジェクトに追加する方法はありますか?