Jak umieścić wszystko w Java hashMap zawartość jednej do drugiej, ale nie zastępować istniejących kluczy i wartości?

83

Muszę skopiować wszystkie klucze i wartości z jednego A HashMap do innego B, ale nie zastępować istniejących kluczy i wartości.

Jak najlepiej to zrobić?

Zamiast tego zastanawiałem się nad iteracją zestawu kluczy i sprawdzeniem, czy istnieje, czy nie

Map temp = new HashMap(); // generic later
temp.putAll(Amap);
A.clear();
A.putAll(Bmap);
A.putAll(temp);
rapadura
źródło

Odpowiedzi:

108

Wygląda na to, że chcesz utworzyć tymczasowy Map, więc zrobiłbym to w ten sposób:

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

Oto patchmapa, którą dodajesz do targetmapy.

Dzięki Louisowi Wassermanowi, oto wersja korzystająca z nowych metod Java 8:

patch.forEach(target::putIfAbsent);
erickson
źródło
W tym przypadku nie musisz tego robić, removeAllponieważ i tak zostaną one zastąpione.
Wielebny Gonzo
@Reverend Gonzo: Zastąpiony przez co?
erickson,
@luksmir Nie, to spowoduje usunięcie istniejących wpisów, które powinny zostać zachowane.
erickson,
Cześć! Dlaczego mapWithValues.putAll (mapWithAnotherValues) nie działa?
betomoretti
15
@erickson znacznie bardziej kompaktowej wersji Java 8: patch.forEach(target::putIfAbsent).
Louis Wasserman,
15

Korzystanie z guawy 's mapy metod klasy narzędzie do obliczania różnicy 2 mapach można to zrobić w jednej linii, metodą podpisu, co czyni go bardziej jasne, co chce się osiągnąć:

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
źródło
8

Po prostu przeprowadź iterację i dodaj:

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

Edytuj, aby dodać:

Jeśli możesz wprowadzić zmiany w a, możesz również:

a.putAll(b)

a testament będzie miał dokładnie to, czego potrzebujesz. (wszystkie wpisy w bi wszystkie wpisy a, których nie ma b)

Wielebny Gonzo
źródło
1.) entrySet()zwraca a Set<Map.Entry>. 2.) Nie ma metody contains(...)na java.util.Map.
Fabian Barney,
Czy nie ma mądrzejszego sposobu? Podoba Ci się narzędzie kolekcji? Nienawidzę wszystkich pętli for wszędzie.
rapadura,
1
@AntonioP: Wszystkie pętle for są wszędzie? Jest jedna pętla for i jest tak prosta, jak tylko możesz.
Wielebny Gonzo,
Wtedy +1 działa tylko wtedy, gdy Mapy nie są używane z typem surowym, jak sądzę. Jestem trochę zamroczony Mapą. Wejście :-)
Fabian Barney
@Reverend Gonzo, ah, w innym miejscu kodu. :) Wont .putAll zastąpi istniejące klucze i wartości? Podążę z tym poczuciem, to wydaje się najprostszy sposób.
rapadura,
5

Możesz to zrobić w zaledwie 1 linii, jeśli zmienisz kolejność map w rozwiązaniu @ erickson:

mapWithNotSoImportantValues.putAll( mapWithImportantValues );

W tym przypadku zamieniasz wartości w mapWithNotSoImportantValues ​​na wartość z mapWithImportantValues ​​z tymi samymi kluczami.

Anatolii Stepaniuk
źródło
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
źródło
2

W Javie 8 istnieje metoda API, która spełnia Twoje wymagania.

map.putIfAbsent(key, value)

Jeśli określony klucz nie jest już skojarzony z wartością (lub jest zamapowany na null), kojarzy go z daną wartością i zwraca null, w przeciwnym razie zwraca bieżącą wartość.

nowy dzień
źródło
1
czy mogliśmy wstawić AllIfAbsent? to jest to, czego potrzebuję ?
user1735921
0

Jak powiedzieli inni, możesz użyć putIfAbsent. Powtórz każdy wpis na mapie, który chcesz wstawić, i wywołaj tę metodę na oryginalnej mapie:

mapToInsert.forEach(originalMap::putIfAbsent);
whistling_marmot
źródło