Как удалить Set, который используется в качестве значения, из ConcurrentHashMap? - PullRequest
0 голосов
/ 03 марта 2019

Давайте рассмотрим следующий код:

ConcurrentHashMap<String, Set<String>> map = new ConcurrentHashMap<>();

// Add element: {mapKey, setValue}

map.computeIfAbsent(mapKey, new Function<String, Set<String>>() {
    @Override
    public Set<String> apply(String mapK) {
        return ConcurrentHashMap.newKeySet();
    }
}).add(setValue);

// Remove element: {mapKey, setValue}

Set<String> updatedSet = map.computeIfPresent(mapKey, new BiFunction<String, Set<String>, Set<String>>() {
    @Override
    public Set<String> apply(String mapK, Set<String> old) {
        old.remove(setValue);
        return old;
    }
});

// I need remove mapKey, but I cannod do this like this, because of race condition bug
if (updatedSet.isEmpty()) {
    map.remove(mapKey);
}

Итак, что мы можем увидеть:

  1. У нас есть ConcurrentHashMap<String, Set<String>> карта, где key карта String, а value - это ConcurrentHashSet.
  2. Мне нужно удалить set, значение map, когда set равно empty.
  3. Iне могу реализовать наивное удаление set из-за ошибки состояния гонки.

Есть ли какое-нибудь блестящее решение моей проблемы?

1 Ответ

0 голосов
/ 03 марта 2019

computeIfPresent удаляет запись, если преобразователь возвращает null.Вместо того, чтобы выполнять удаление на отдельном шаге, верните null из картографа, если вы хотите удалить запись.

(Кроме того, вам действительно нужно сложить .add(setValue) в свой картограф computeIfAbsent, ииспользуйте compute вместо computeIfAbsent, потому что вы сейчас ничего не делаете для защиты вызова add. Использование merge также будет вариантом.)

...