【问题标题】:Java: add to map of collectionsJava:添加到集合地图
【发布时间】:2016-11-02 02:18:41
【问题描述】:

我正在尝试编写一个通用函数,它将一个元素添加到Collections 的Map。这适用于MapLists:

public static <TKey, TVal> void addToMapOfLists(Map<TKey, List<TVal>> map, TKey key, TVal val) {
    List<TVal> list = map.get(key);
    if (list == null) {
        list = new ArrayList<>();
        list.add(val);
        map.put(key, list);
    } else
        list.add(val);
}

我想让这个函数在Map&lt;TKey, Set&lt;TVal&gt;&gt;Map&lt;TKey, List&lt;TVal&gt;&gt; 上工作。我希望这应该是可能的,因为两者都实现了Collection,它具有我调用的add(TVal) 成员。

我的问题是,当我尝试将参数 Map&lt;TKey, List&lt;TVal&gt;&gt; map 更改为 Map&lt;TKey, ? extends Collection&lt;TVal&gt;&gt; map - 我需要以某种方式将 new ArrayList&lt;&gt;(); 替换为对 Collection 实现者的构造函数的调用。

【问题讨论】:

  • 您是如何选择使用 List 或 Set 的?通过 java 中的反射,您在运行时找不到参数 Map 的泛型类型。
  • 显然(来自 C++)- 根据地图类型选择列表或集合。两者都调用了默认 ctor。
  • @AnkitTripathi,我在问这个问题之前看过这个问题。该问题询问有关定义新类型的问题,并且询问有关添加到现有地图的问题。答案对这个问题也不是很有用。

标签: java generics dictionary collections


【解决方案1】:

您必须向您的方法传递一个附加参数 - SupplierCollection 实例。

这是一种可能的实现方式:

public static <TKey, TVal, TCol extends Collection<TVal>> void addToMapOfCollections(Map<TKey, Collection<TVal>> map, TKey key, TVal val, Supplier<TCol> supplier) 
{
    Collection<TVal> col = map.get(key);
    if (col == null) {
        col = supplier.get ();
        col.add(val);
        map.put(key, col);
    } else {
        col.add(val);
    }
}

这是另一种选择:

public static <TKey, TVal> void addToMapOfCollections(Map<TKey, Collection<TVal>> map, TKey key, TVal val, Supplier<Collection<TVal>> supplier)
{
    Collection<TVal> col = map.get(key);
    if (col == null) {
        col = supplier.get ();
        col.add(val);
        map.put(key, col);
    } else {
        col.add(val);
    }
}

而且代码更少(正如 Gerald 所建议的那样):

public static <TKey, TVal> void addToMapOfCollections(Map<TKey, Collection<TVal>> map, TKey key, TVal val, Supplier<Collection<TVal>> supplier)
{
    map.putIfAbsent(key, supplier.get());
    map.get(key).add(val);
}

我测试了第二个变体:

Map<String,Collection<Integer>> map = new HashMap<String, Collection<Integer>>();
addToMapOfCollections(map,"String1",5,HashSet::new);
addToMapOfCollections(map,"String2",67,ArrayList::new);
addToMapOfCollections(map,"String2",68,ArrayList::new);
System.out.println (map);
for (Collection<Integer> col : map.values ()) {
    System.out.println (col.getClass () + " : " + col);
}

输出:

{String2=[67, 68], String1=[5]}
class java.util.ArrayList : [67, 68]
class java.util.HashSet : [5]

【讨论】:

  • 可以通过使用putIfAbsent 初始化集合对该方法进行额外的简化:map.putIfAbsent(key, supplier.get()); map.get(key).add(value)
  • @GeraldMücke 好建议。
猜你喜欢
  • 1970-01-01
  • 2016-10-17
  • 1970-01-01
  • 2016-06-13
  • 2013-03-25
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多