一个常见的用例是maps 和collections,比如
Map<String, Collection<String>> strings = new HashMap<>();
computeIfAbsent 和computeIfPresent 是在集合中添加和删除元素的非常方便的操作。尤其是因为与put() 不同,compute*() 方法返回当前值(无论它是否刚刚创建)。这是一个按字符串的第一个字符分组的示例。请注意,键和集合都是在必要时创建的,并在集合变为空时对其进行清理:
void addString(String a) {
String index = a.substring(0, 1);
strings.computeIfAbsent(index, ign -> new HashSet<>()).add(a);
}
void removeString(String a) {
String index = a.substring(0, 1);
strings.computeIfPresent(index, (k, c) -> {
c.remove(a);
return c.isEmpty() ? null : c;
});
}
例子:
// {}
addString("a1"); // {a=[a1]} <-- collection dynamically created
addString("a2"); // {a=[a1, a2]}
removeString("a1"); // {a=[a2]}
removeString("a2"); // {} <-- both key and collection removed
这在多线程环境中非常强大,因为ConcurrentMaps 以原子方式执行这些操作。
删除操作可以是单行的:
void removeString(String a) {
String index = a.substring(0, 1);
strings.computeIfPresent(index, (i, c) -> c.remove(a) && c.isEmpty() ? null : c);
}
简而言之:
Map<String, Set<String>> map = new ConcurrentHashMap<>();
map.computeIfAbsent(key, i -> ConcurrentHashMap.newKeySet()).add(value);
map.computeIfPresent(key, (i, s) -> s.remove(value) && s.isEmpty() ? null : s);