简体   繁体   English

ConcurrentHashMap-添加具有相同Key的项目

[英]ConcurrentHashMap - adding items with the same Key

I have a CuncurrentHasMap: 我有一个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). 我用相同的键推送(有时)对象,这些对象是TreeMap(string,MyPrivateClass)类型的TreeMap。

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 : 使值List<Object> (或其他一些容器/集合类型),而不是Object

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

and then use compute instead of put to create and add to the list: 然后使用compute而不是put来创建并添加到列表中:

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 . 如果您可以接受,则可以使用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: 由于看起来您需要一个线程安全的Map,因此我将使用Multimaps.synchronizedMultimap方法并执行以下操作:

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: 正如您在评论中所述,应将新的TreeMap类型值与现有值合并 ,您可以重写字段并put方法,如下所示:

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. 使用ConcurrentHashMap表示您将从多个线程同时访问地图,这就是为什么我添加Collections.synchronizedMap()因为您可能还希望同时对结果TreeMap执行读取。

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. 更新:在仍然维护TreeMaps条目的同时,我像AndyTurner在他的回答中那样,从computeIfAbsent切换到了compute ,因为我以前的方法不是原子方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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