Wie kann man alle Java-HashMap-Inhalte von einem zum anderen setzen, aber vorhandene Schlüssel und Werte nicht ersetzen?

82

Ich muss alle Schlüssel und Werte von einer A-HashMap auf eine andere B kopieren, aber vorhandene Schlüssel und Werte nicht ersetzen.

Was ist der beste Weg, das zu tun?

Ich dachte stattdessen, ich würde das keySet iterieren und prüfen, ob es existiert oder nicht

Map temp = new HashMap(); // generic later
temp.putAll(Amap);
A.clear();
A.putAll(Bmap);
A.putAll(temp);
Rapadura
quelle

Antworten:

107

Es sieht so aus, als ob Sie bereit sind, eine temporäre Datei zu erstellen. MapIch würde es also so machen:

Map tmp = new HashMap(patch);
tmp.keySet().removeAll(target.keySet());
target.putAll(tmp);

Hier patchist die Karte, die Sie der targetKarte hinzufügen .

Dank Louis Wasserman gibt es hier eine Version, die die neuen Methoden in Java 8 nutzt:

patch.forEach(target::putIfAbsent);
erickson
quelle
In diesem Fall müssen Sie dies nicht tun, removeAllda sie sowieso überschrieben werden.
Reverend Gonzo
@Reverend Gonzo: Von was überschrieben?
Erickson
@luksmir Nein, das würde die vorhandenen Einträge entfernen, die erhalten bleiben sollten.
Erickson
Hallo! Warum funktioniert mapWithValues.putAll (mapWithAnotherValues) nicht?
Betomoretti
15
@erickson eine viel kompaktere Java 8-Version : patch.forEach(target::putIfAbsent).
Louis Wasserman
15

Mit Guava ‚s Karten Klasse‘ Utility Methoden , um die Differenz von 2 Karten berechnen Sie es in einer einzigen Zeile tun, mit einer Signatur der Methode , die es macht klar , was Sie versuchen zu erreichen:

public static void main(final String[] args) {
    // Create some maps
    final Map<Integer, String> map1 = new HashMap<Integer, String>();
    map1.put(1, "Hello");
    map1.put(2, "There");
    final Map<Integer, String> map2 = new HashMap<Integer, String>();
    map2.put(2, "There");
    map2.put(3, "is");
    map2.put(4, "a");
    map2.put(5, "bird");

    // Add everything in map1 not in map2 to map2
    map2.putAll(Maps.difference(map1, map2).entriesOnlyOnLeft());
}
Tom Tresansky
quelle
8

Einfach iterieren und hinzufügen:

for(Map.Entry e : a.entrySet())
  if(!b.containsKey(e.getKey())
    b.put(e.getKey(), e.getValue());

Bearbeiten, um hinzuzufügen:

Wenn Sie Änderungen an a vornehmen können, können Sie auch Folgendes tun:

a.putAll(b)

und ein Wille hat genau das, was Sie brauchen. (alle Einträge in bund alle Einträge in a, die nicht in sind b)

Reverend Gonzo
quelle
1.) entrySet()gibt a zurück Set<Map.Entry>. 2.) Es gibt keine Methode contains(...)für java.util.Map.
Fabian Barney
Gibt es keinen klügeren Weg? Wie ein Sammlungsdienstprogramm oder so? Ich hasse alle for-Schleifen überall.
Rapadura
1
@AntonioP: Alle for-Schleifen überall? Es gibt eine for-Schleife und sie ist so einfach wie möglich.
Reverend Gonzo
+1 funktioniert dann nur, wenn Maps nicht mit Raw-Typ verwendet werden, denke ich. Habe mich ein bisschen mit der Map beschäftigt. Eintrag :-)
Fabian Barney
@Reverend Gonzo, ah, an anderer Stelle im Code. :) Wird nicht .putAll vorhandene Schlüssel und Werte von a ersetzen? Ich gehe mit diesem Gefühl, es scheint der einfachste Weg zu sein.
Rapadura
5

Sie können es in nur einer Zeile machen, wenn Sie die Kartenreihenfolge in @ ericksons Lösung ändern:

mapWithNotSoImportantValues.putAll( mapWithImportantValues );

In diesem Fall ersetzen Sie Werte in mapWithNotSoImportantValues ​​durch Werte aus mapWithImportantValues ​​mit denselben Schlüsseln.

Anatolii Stepaniuk
quelle
2
public class MyMap {

public static void main(String[] args) {

    Map<String, String> map1 = new HashMap<String, String>();
    map1.put("key1", "value1");
    map1.put("key2", "value2");
    map1.put("key3", "value3");
    map1.put(null, null);

    Map<String, String> map2 = new HashMap<String, String>();
    map2.put("key4", "value4");
    map2.put("key5", "value5");
    map2.put("key6", "value6");
    map2.put("key3", "replaced-value-of-key3-in-map2");
    // used only if map1 can be changes/updates with the same keys present in map2.
    map1.putAll(map2);

    // use below if you are not supposed to modify the map1.
    for (Map.Entry e : map2.entrySet())
        if (!map1.containsKey(e.getKey()))
            map1.put(e.getKey().toString(), e.getValue().toString());
    System.out.println(map1);
}}
Jajikanth pydimarla
quelle
2

Mit Java 8 gibt es diese API-Methode, um Ihre Anforderungen zu erfüllen.

map.putIfAbsent(key, value)

Wenn der angegebene Schlüssel noch keinem Wert zugeordnet ist (oder null zugeordnet ist), ordnet er dem angegebenen Wert zu und gibt null zurück, andernfalls wird der aktuelle Wert zurückgegeben.

neuer Tag
quelle
1
können wir putAllIfAbsent haben? das ist was ich brauche ?
user1735921