Eclipse CollectionsMutableMapIterable.updateValueWith(K key, Function0<? extends V> factory, Function2<? super V,? super P,? extends V> function, P parameter)
から使用できます。
マップに何もない場合、factory
引数は初期値を作成します。引数は、function
追加のパラメーターとともにマップ値に適用され、新しいマップ値が作成されます。それparameter
は への最終引数として渡されますupdateValueWith()
。キーがマップにない場合でも関数が呼び出されます。したがって、初期値は実際にはとfunction
の出力に適用されます。値を変更してはなりません。新しい値を返す必要があります。あなたの例では、マップ値は不変の文字列であるため、問題ありません。factory
parameter
function
のような ConcurrentMapsorg.eclipse.collections.impl.map.mutable.ConcurrentHashMap
では、 の実装updateValueWith()
もスレッドセーフでアトミックです。function
マップ値を変更しないことが重要です。そうしないと、スレッドセーフではなくなります。代わりに新しい値を返す必要があります。あなたの例では、マップ値は不変の文字列であるため、問題ありません。
メソッドrecalculateNewValue()
が文字列の連結のみを行う場合は、次のように使用できますupdateValueWith()
。
Function0<String> factory = () -> "initial ";
Function2<String, String, String> recalculateNewValue = String::concat;
MutableMap<String, String> map = new ConcurrentHashMap<>();
map.updateValueWith("test", factory, recalculateNewValue, "append1 ");
Assert.assertEquals("initial append1 ", map.get("test"));
map.updateValueWith("test", factory, recalculateNewValue, "append2");
Assert.assertEquals("initial append1 append2", map.get("test"));
Java 8 のConcurrentMap.compute(K key, BiFunction remappingFunction)を使用して同じことを達成できますが、いくつかの欠点があります。
ConcurrentMap<String, String> map = new ConcurrentHashMap<>();
map.compute("test", (key, oldValue) -> oldValue == null ? "initial append1 " : oldValue + "append1 ");
Assert.assertEquals("initial append1 ", map.get("test"));
map.compute("test", (key, oldValue) -> oldValue == null ? "initial append1 " : oldValue + "append2");
Assert.assertEquals("initial append1 append2", map.get("test"));
- キーが存在しない場合を処理する別のファクトリがないため、ラムダの本体で値と初期値を処理する必要があります。
- API は、ラムダの再利用に適していません。へのすべての呼び出し
updateValueWith()
は同じラムダを共有しますが、へのすべての呼び出しcompute()
はヒープに新しいガベージを作成します。
注: 私は Eclipse Collections のコミッターです。