Распространенным вариантом использования являются карты с < href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html" rel="nofollow noreferrer">коллекции, например
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
< /a> выполнять эти операции атомарно.
Операция удаления может быть однострочной:
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);
person
steffen
schedule
01.09.2016