简体   繁体   中英

ConcurrentHashMap - adding items with the same Key

I have a CuncurrentHasMap:

private static ConcurrentHashMap<String, Object> testParameters =
new ConcurrentHashMap<String, Object>();

I am pushing (sometimes) objects with the same keys, those objects are TreeMaps of type TreeMap(string, MyPrivateClass).

How to change this put method, so that objects with same key will be placed together and not be overridden?

public static void put(String key, Object object) {

        getTestParameters().put(key, object);
}

Make the value List<Object> (or some other container/collection type), instead of Object :

private static ConcurrentHashMap<String, List<Object>> testParameters =
    new ConcurrentHashMap<>();

and then use compute instead of put to create and add to the list:

getTestParameters().compute(key, (k, v) -> {
  if (v == null) v = new ArrayList<>();
  v.add(object);
  return v;
});

If this is acceptable to you, you could use an implementation of Guava Multimap . It can stores multiple values for a single key. Since it looks like you need a Map which is thread-safe, I would use the Multimaps.synchronizedMultimap method and do something like this:

Multimap<String, Object> multimap = HashMultimap.create();
Multimap synchronizedMultimap = Multimaps.synchronizedMultimap(multimap);

As you stated in comments that new TreeMap typed values should be merged with existing ones, you can rewrite your field and put method like this:

private static final Map<String, Map<String, MyPrivateClass>> testParameters = new ConcurrentHashMap<>();

public static void put(String key, TreeMap<String, MyPrivateClass> value) {
    testParameters.compute(key, (k,v) -> {
            if(null == v) {
                v = Collections.synchronizedMap(new TreeMap<>(value.comparator()));
            }
            v.putAll(value);
            return v;
        }
    );
}

The use of ConcurrentHashMap indicates that you are going to access the map concurrently from multiple threads, this is why I added Collections.synchronizedMap() as you likely also want to perform reads concurrently on the resulting TreeMaps.

Update: While still maintaining the TreeMaps' entries, I switched from computeIfAbsent to compute as AndyTurner does in his answer because my former approach was not atomic.

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