2008-10-31 3 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: } 

и ListMap выглядит почти так же, за исключением строки 7, где я делаю новый ArrayList. Такое дублирование достаточно мало, чтобы быть терпимым, но остается вопрос, возможно ли такое «вложенные дженерики» в Java?

EDIT:

Как 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); 
     } 
    } 
} 

и ListMap и SetMap только обеспечивают надлежащий сбор

ответ

9

Если map - Map<K, Collection<V>>, используйте idiom computeIfAbsent(...).add(...), так:

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

Или, для Set:

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

Если это вариант, вы можете просто использовать Google Collections API - http://code.google.com/p/google-collections/.

Даже если вы не можете его использовать, возможно, взглянув на то, как они реализовали свои MultiMaps, вы поможете вам в реализации.

2

Существует проблема с кодом:

Коллекция с = новая коллекция();

Невозможно создать экземпляр.

Я думаю, что следующий фрагмент кода будет решить вашу проблему:

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 Коллекция также предлагает Multimap, но это предварительно JDK 1-0,5, так что вы не будете иметь безопасности дженерик там , Вы можете обернуть его в коллекции Collections.checkedMap (Key.class, Value.class, collection) для обеспечения безопасности во время выполнения. Если вы можете использовать API Colelction от Google, он предлагает еще один мультиплексор 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); 

 Смежные вопросы

  • Нет связанных вопросов^_^