您可以MutableMapIterable.updateValueWith(K key, Function0<? extends V> factory, Function2<? super V,? super P,? extends V> function, P parameter)
从Eclipse Collections使用。
如果地图中没有任何值,则该factory
参数会创建一个初始值。该function
参数与附加参数一起应用于地图值,以得出新的地图值。这parameter
作为最终参数传递给updateValueWith()
. 即使键不在地图中,也会调用该函数。所以初始值实际上是function
应用于 和 的factory
输出parameter
。function
不能改变值;它应该返回一个新值。在您的示例中,地图值是不可变的字符串,所以我们很好。
在 ConcurrentMaps likeorg.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"));
- 没有单独的工厂来处理缺少键的情况,因此 lambda 的主体必须处理值和初始值。
- API 不适合重用 lambda。每次调用都
updateValueWith()
共享相同的 lambda,但每次调用compute()
都会在堆上创建新的垃圾。
注意:我是 Eclipse Collections 的提交者