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

时间:2018-11-26 11:49:26

标签: java concurrency

我有一个CuncurrentHasMap:

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

我(有时)使用相同的键推入对象,这些对象是TreeMap(string,MyPrivateClass)类型的TreeMap。

如何更改此put方法,以便将具有相同键的对象放在一起而不被覆盖?

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

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

3 个答案:

答案 0 :(得分:5)

使用值List<Object>(或其他容器/集合类型)代替Object

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

,然后使用compute代替put创建并添加到列表:

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

答案 1 :(得分:0)

如果您可以接受,则可以使用Guava Multimap的实现。它可以为单个键存储多个值。由于看起来您需要一个线程安全的Map,因此我将使用Multimaps.synchronizedMultimap method并执行以下操作:

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

答案 2 :(得分:0)

正如您在评论中所述,应将新的TreeMap类型值与现有值合并,您可以像这样重写字段和put方法:

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

public static void put(String key, TreeMap<String, MyPrivateClass> value) {
    Map<String, MyPrivateClass> currentValue = testParameters.get(key);
    if(null == currentValue) {
        // create new sub map
        TreeMap<String, MyPrivateClass> newValue = new TreeMap<>(value);
        testParameters.put(key, Collections.synchronizedMap(newValue));
    } else {
        // merge values' entries into existing sub map.
        currentValue.putAll(value);
    }
}

可以写得更短:

public static void put(String key, TreeMap<String, MyPrivateClass> value) {
    testParameters.computeIfAbsent(key, k -> (
      Collections.synchronizedMap(
      new TreeMap<>(value.comparator())))).putAll(value);
}

使用ConcurrentHashMap表示您将从多个线程同时访问地图,这就是为什么我添加了Collections.synchronizedMap()