2014-07-01 16 views
6

Poszukuje standardowej funkcji biblioteki funkcji w Javie do dodawania wartości w dwóch mapach na podstawie ich kluczy.dodawanie wartości dwóch map, gdy ten sam klucz

Map A: {a=1, b=2} 
Map B: {a=2, c=3} 

Wynikające mapa:

Map C: {a=3, b=2, c=3} 

Wiem, że to może być kodowane w kilku liniach. Wiem też, że programowanie funkcjonalne świetnie się do tego nadaje. Po prostu wędruję, jeśli istnieje standardowa funkcja lub składnia, której używają ludzie.

Coś podobnego (ale chyba bardziej ogólny niż):

public HashMap<String,Double> addValues(HashMap<String,Double> a, HashMap<String,Double> b) { 
    HashMap<String,Double> ret = new HashMap<String,Double>(a); 
    for (String s : b.keySet()) { 
     if (ret.containsKey(s)) { 
     ret.put(s, b.get(s) + ret.get(s)); 
     } else { 
     ret.put(s, b.get(s)); 
     } 
    } 
    return ret; 
    } 

+0

To powinno ci pomóc ... http://docs.oracle.com/javase/7/docs/api/java/util/Set.html – JNL

+2

Jaką masz bazę danych ? W pytaniu wpisujesz 'Set', ale dodajesz znacznik' map' – Jens

+0

Sorry Jens Miałem na myśli mapy, teraz poprawione. –

Odpowiedz

1

myślę co robisz jest po prostu w porządku. Mogę wymyślić inny sposób, używając MultiMap. Możesz dodać wszystkie swoje elementy do multimapy, a następnie uruchomić funkcję sumowania dla wszystkich wartości dla każdego klawisza na końcu.

+0

Dziękuję Nie wiedziałem o MultiMaps –

3

Alternatywą, która ma w zasadzie to samo, używając Java 8 new getOrDefault method:

Set<String> keys = new HashSet<> (a.keySet()); 
keys.addAll(b.keySet()); 

Map<String, Integer> c = new HashMap<>(); 
for (String k : keys) { 
    c.put(k, a.getOrDefault(k, 0) + b.getOrDefault(k, 0)); 
} 

Ale jeśli przy użyciu języka Java 8, można także przesyłać klucze i stała się ona jedną wkładkę:

Map<String, Object> c = Stream.concat(a.keySet().stream(), b.keySet().stream()) 
     .distinct() 
     .collect(toMap(k -> k, k -> a.getOrDefault(k, 0) + b.getOrDefault(k, 0))); 
+1

Rozwiązanie strumieniowe nadal wydaje się trochę gadatliwe, ale miło, że jest to co najmniej możliwe teraz. Spodobałoby mi się coś w stylu 'new HashMap <>(). PutAll (a) .mergeAll (b, (v1, v2) -> v1 + v2)'. Nie można jednak znaleźć niczego, co odpowiada mergeAll w dokumentach. Oczywiście strumienie są bardziej ogólne niż wiele specjalistycznych metod. – Chris

+0

Nie sądzę, że jest znacznie krótszy, ale być może przeoczyłem lepszy sposób ... – assylias

+0

Dzięki, bardzo interesujące, chociaż szukałem rozwiązania Java 6/7. –

0

Oto wersja, która umożliwia połączenie dowolnej liczby Maps:

public static Map<String, Integer> addKeys(Map<String, Integer>... maps) { 
    Set<String> keys = new HashSet<String>(); 
    for (Map<String, Integer> map : maps) 
     keys.addAll(map.keySet()); 

    Map<String, Integer> result = new HashMap<String, Integer>(); 
    for (String key : keys) { 
     Integer value = 0; 
     for (Map<String, Integer> map : maps) 
      if (map.containsKey(key)) 
       value += map.get(key); 
     result.put(key, value); 
    } 
    return result; 
} 

Zastosowanie:

public static void main(String[] args){ 
    Map<String, Integer> a = new HashMap<String, Integer>(); 
    a.put("a", 1); 
    a.put("b", 2); 
    Map<String, Integer> b = new HashMap<String, Integer>(); 
    b.put("a", 2); 
    b.put("c", 3); 

    Map<String, Integer> c = addKeys(a, b); 
    System.out.println(c); 
} 

ouptut:

{b=2, c=3, a=3} 

Niestety, to nie jest możliwe, o ile widzę, aby stworzyć ogólną metodę:

public static <K, V extends Number> Map<K, V> addKeys(Class<V> cls, Map<K, V>... maps); 

Ponieważ klasa Number nie obsługuje operatora +. Co wydaje mi się trochę dziwne ...

Powiązane problemy