2008-10-31 77 views
3

的我想作的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> 

但編譯器抱怨<V>部分,並且仍然存在製作適當的新集合的問題。

此刻,我做了兩個類:的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: } 

和列表地圖看起來非常除非我做出新的ArrayList中的7號線相同。這種重複是足夠小,可以忍受的,但問題仍然是Java中可能存在的這種「嵌套泛型」?

編輯:

由於erickson said,解決方案是在<A, B extends Something<A>>,而不是僅僅<B extends Something<A>>

這樣的代碼可以看起來像

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); 
     } 
    } 
} 

和列表地圖和的setMap只提供正確的收集

回答

9

如果mapMap<K, Collection<V>>,則使用習語computeIfAbsent(...).add(...),這樣的:

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

或者,對於Set

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

您的代碼存在問題:

Collection 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); 
     } 
    } 
} 
+0

是的,我已經提到了,它只是在那裏ilustrate的想法 – Slartibartfast 2008-10-31 18:12:41

2

的Apache Commons Collections中還提供了一個多重映射,但它的預JDK 1 - 0.5,所以你沒有仿製藥存在安全。您可以將它包裝在一個Collections.checkedMap(Key.class,Value.class,集合)中以實現運行時安全。如果您可以使用Google的Colelction API,那麼它可以提供具有所有泛型,鈴聲和哨聲的更加輕鬆的MultiMap。

2

如果可能,請使用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);