简体   繁体   中英

Is there any Concurrent multi valued HashMap data structure in java?

I have a requirement to have key value pairs, where the value can be a set. This data structure should be thread safe to add remove elements to the set in a multi threaded environment.

My requirement is to create a subscription list, here people can subscribe for different topics. This subscription list should be concurrent, thread safe and fast. I was thinking about Using ConcurentHashMap and ConcurrentHashSet, this will not help me since, I have to put the syncronization block at the top level and it will block the entire map until the put/remove operation completes.

There is no pre-rolled solution, but it is possible to achieve thread-safe concurrency for simple values using a ConcurrentMap<K, Set<V>> which has Set<V> values made from ConcurrentMap<V, Boolean> using Collections.newSetFromMap(Map<V,Boolean>) .

Then, to get each value set in an atomic way, use ConcurrentMap.computeIfAbsent(K, Function<? super K, ? extends Set<V>>) :

ConcurrentMap<String, Set<Integer>> multimap = new ConcurrentHashMap<>();
Set<Integer> fooValues = multimap.computeIfAbsent("foo", key -> Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>()));

If you want your values to have a stable iteration order, you can use a ConcurrentSkipListSet to hold values instead:

ConcurrentMap<String, NavigableSet<Integer>> multimap = new ConcurrentHashMap<>();
NavigableSet<Integer> fooValues = multimap.computeIfAbsent("foo", key -> new ConcurrentSkipListSet<>());

Likewise, in order to remove Set<V> value holder instances in a thread-safe fashion, you can use ConcurrentMap.computeIfPresent(K, BiFunction<? super K,? super Set<V>,? extends Set<V>>) :

public static <K, V> void remove(final ConcurrentMap<K, Collection<? extends V>> multimap, final K key,
        final V value) {
    multimap.computeIfPresent(key, (k, oldValues) -> {
        final Collection<? extends V> newValues;
        if (oldValues.remove(value) && oldValues.isEmpty()) {
            // Remove the empty set from the multimap
            newValues = null;
        } else {
            newValues = oldValues;
        }
        return newValues;
    });
}

Note that there is no " ConcurrentHashSet " class provided by the Java core libraries .

you write "the value can be a set", but don't mention what the key is. In any case, Hashtable, the first map that was present in Java, is thread safe wrt adding/removing/replacing key,value pairs.

You can create a thread-safe Set with one of the methods described here . Whether that set is stored as value in an hashmap makes no difference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM