2014-07-01 7 views
6

Suchen Sie nach einer Standardbibliotheksfunktion in Java, um die Werte in zwei Maps basierend auf ihren Schlüsseln hinzuzufügen.Addieren der Werte von zwei Maps bei gleichem Schlüssel

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

Resultierende Karte:

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

ich das erkennen kann in wenigen Zeilen codiert werden. Ich weiß auch, dass funktionale Programmierung dafür großartig ist. Ich bin nur herumwandernd, wenn es eine Standardfunktion oder Syntax gibt, die Leute da draußen benutzen.

So etwas (aber wahrscheinlich mehr als generische):

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

Dies sollte Ihnen helfen ... http://docs.oracle.com/javase/7/docs/api/java/util/Set.html – JNL

+2

Welche Datenstruktur Sie haben ? In Frage schreibst du 'Set', aber du fügst' map' tag – Jens

+0

Sorry Jens ich meinte Karten, jetzt korrigiert. –

Antwort

1

denke ich, was Sie tun einfach gut ist. Ich kann jedoch eine andere Art und Weise denken, mit einem MultiMap. Sie können alle Ihre Elemente zu einer Multimap hinzufügen und dann eine Summierungsfunktion über alle Werte für jeden Schlüssel am Ende ausführen.

+0

Vielen Dank Ich wusste nicht über MultiMaps –

3

Eine Alternative, die im Wesentlichen die gleiche Sache tut, mit 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)); 
} 

Aber wenn mit Hilfe von Java 8, auch Sie können die Schlüssel streamen und es eine Einzeiler machen:

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

Die Streams Lösung scheint immer noch ein wenig wortreich, aber es ist schön, dass es jetzt zumindest möglich ist. Ich hätte etwas in der Art von 'new HashMap <>() gemocht. PutAll (a) .mergeAll (b, (v1, v2) -> v1 + v2)'. Es kann jedoch nichts gefunden werden, das mergeAll in den Dokumenten entspricht. Und natürlich sind Streams allgemeiner als viele spezialisierte Methoden. – Chris

+0

Ich glaube nicht, dass es viel kürzer ist, aber ich könnte einen besseren Weg verpasst haben ... – assylias

+0

Danke, sehr interessant, obwohl ich nach einer Java 6/7 Lösung suchte. –

0

Hier ist eine Version, die es ermöglicht, eine beliebige Anzahl von Maps zu kombinieren:

Verbrauch:

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} 

Leider ist es nicht möglich, soweit ich eine generische Methode erstellen sehen:

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

Da die Number Klasse nicht Unterstützen Sie den Operator +. Das scheint mir ein bisschen dämlich ...

Verwandte Themen