【问题标题】:Map of collections馆藏地图
【发布时间】:2008-10-31 17:47:50
【问题描述】:

我想用 Java 制作集合地图,所以我可以制作类似的东西

public void add(K key, V value) {  
    if (containsKey(key)) {
        get(key).add(value);
    } else {
        Collection c = new Collection();
        c.add(value);
        put(key, value);
    }
}

我试着用类似的东西来实现它

public class CollectionMap<K, C extends Collection<V>> extends HashMap<K, C>

但是编译器抱怨&lt;V&gt; 部分,并且仍然存在制作正确的新集合的问题。

目前,我制作了两个类:SetMap,看起来像这样

 1: public class SetMap<K, V> extends HashMap<K, Set<V>> {
 2: 
 3:    public void add(K key, V value) {
 4:        if (containsKey(key)) {
 5:            get(key).add(value);
 6:        } else {
 7:            Set<V> list = new HashSet<V>();
 8:            list.add(value);
 9:            put(key, list);
10:        }
11:    }
12:
13: }

和 ListMap 看起来几乎一样,除了我创建新 ArrayList 的第 7 行。这种重复小到可以容忍,但问题仍然存在,这种“嵌套泛型”在 Java 中是否可行?

编辑:

作为erickson said,解决方案在&lt;A, B extends Something&lt;A&gt;&gt; 而不仅仅是&lt;B extends Something&lt;A&gt;&gt;

所以代码看起来像

public abstract class CollelctionMap<K, V, C extends Collection<V>> extends HashMap<K, C> {

    protected abstract C newCollection();

    public void add(K key, V value) {
        if (containsKey(key)) {
            get(key).add(value);
        } else {
            C c = newCollection();
            c.add(value);
            put(key, c);
        }
    }
}

ListMap 和 SetMap 只提供正确的集合

【问题讨论】:

    标签: java generics collections


    【解决方案1】:

    如果mapMap&lt;K, Collection&lt;V&gt;&gt;,请像这样使用成语computeIfAbsent(...).add(...),

    map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
    

    或者,Set

    map.computeIfAbsent(key, k -> new HashSet<>()).add(value);
    

    【讨论】:

      【解决方案2】:

      如果可以选择,您可能只想使用 Google Collections API - http://code.google.com/p/google-collections/

      即使你不能使用它,也许看看他们如何实现他们的 MultiMaps 会帮助你的实现。

      【讨论】:

        【解决方案3】:

        你的代码有问题:

        集合 c = new Collection();

        无法实例化。

        我认为下一段代码会解决你的问题:

        public class CollectionMap<K, V> extends HashMap<K, Collection<V>> {
        
        
            ...
            ...
            ...
        
        
            public void add(K key, V value) {
                if (containsKey(key)) {
                    get(key).add(value);
                } else {
                    Collection<V> c = new ArrayList<V>();
                    c.add(value);
                    super.put(key, c);
                }
            }
        }
        

        【讨论】:

        • 是的,我已经提到过,它只是用来说明一个想法
        【解决方案4】:

        Apache Commons Collections 还提供了 MultiMap,但它是 JDK 1-.5 之前的版本,因此那里没有泛型安全性。您可以将其包装在 Collections.checkedMap(Key.class, Value.class, collection) 中以确保运行时安全。如果您可以使用 Google 的 Colelction API,它会提供一个更流畅的 MultiMap,其中包含所有泛型、花里胡哨的功能。

        【讨论】:

          【解决方案5】:

          如果可能,请使用 Google 的 Guava。伙计们在那里做得很好。

          这是另一种解决方案。

          abstract class MultiMap<K, V> {
          
              private Map<K, Collection<V>> entries = new LinkedHashMap<K, Collection<V>>();
          
              public void put(K key, V value) {
                  Collection<V> values = entries.get(key);
                  if (values == null) {
                      entries.put(key, values = newValueCollection());
                  }
                  values.add(value);
              }
          
              // other methods
              // ..
          
              abstract Collection<V> newValueCollection();
          
          
          
              // Helper methods to create different flavors of MultiMaps
          
              public static <K, V> MultiMap<K, V> newArrayListMultiMap() {
                  return new MultiMap<K, V>() {
                      Collection<V> newValueCollection() {
                          return new ArrayList<V>();
                      }
                  };
              }
          
              public static <K, V> MultiMap<K, V> newHashSetMultiMap() {
                  return new MultiMap<K, V>() {
                      Collection<V> newValueCollection() {
                          return new HashSet<V>();
                      }
                  };
                  }
          
           }
          

          你可以像这样使用它

          MultiMap<String, Integer> data = MultiMap.newArrayListMultiMap();
          data.put("first", 1);
          data.put("first", 2);
          data.put("first", 3);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-07-02
            • 1970-01-01
            • 1970-01-01
            • 2019-07-31
            • 2011-04-06
            • 2019-10-31
            相关资源
            最近更新 更多