Java: ajouter à la carte des collections


Je suis en train d'écrire une fonction générique qui va ajouter un élément à un Map de Collection. s. Cela fonctionne pour un Map de Lists:

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

Je veux faire fonctionner cette fonction sur Map<TKey, Set<TVal>> ainsi que sur Map<TKey, List<TVal>>. Je m'attends à ce que cela soit possible car les deux implémentent Collection qui a le membre add(TVal) que j'appelle.

Mon problème est que lorsque j'essaie de changer le paramètre Map<TKey, List<TVal>> map en Map<TKey, ? extends Collection<TVal>> map - Je dois en quelque sorte remplacer new ArrayList<>(); par un appel au constructeur de l'implémenteur de Collection.

Author: ytoledano, 2016-06-30

1 answers

Vous devrez passer un paramètre supplémentaire à votre méthode - un Supplier des instances Collection.

Voici une implémentation possible :

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

Voici une autre possibilité :

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

Et avec moins de code (comme suggéré par 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);
}

J'ai testé la deuxième variante :

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

Sortie :

{String2=[67, 68], String1=[5]}
class java.util.ArrayList : [67, 68]
class java.util.HashSet : [5]
 7
Author: Eran, 2016-06-30 06:51:23