Как поместить все содержимое Java hashMap одного в другое, но не заменять существующие ключи и значения?

83

Мне нужно скопировать все ключи и значения из одного A HashMap в другой B, но не для замены существующих ключей и значений.

Как лучше всего это сделать?

Я думал вместо того, чтобы повторять keySet и проверять, существует он или нет, я бы

Map temp = new HashMap(); // generic later
temp.putAll(Amap);
A.clear();
A.putAll(Bmap);
A.putAll(temp);
рападура
источник

Ответы:

108

Похоже, вы хотите создать временный объект Map, поэтому я бы сделал это так:

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

Вот patchкарта, которую вы добавляете на targetкарту.

Спасибо Луи Вассерману, вот версия, которая использует преимущества новых методов в Java 8:

patch.forEach(target::putIfAbsent);
Эриксон
источник
В этом случае делать не нужно, removeAllтак как они все равно будут отменены.
Преподобный Гонзо,
@ Преподобный Гонзо: Чем было перезаписано?
erickson
@luksmir Нет, это приведет к удалению существующих записей, которые следует сохранить.
erickson 08
Привет! Почему mapWithValues.putAll (mapWithAnotherValues) не работает?
Betomoretti
15
@erickson гораздо более компактной версии Java 8: patch.forEach(target::putIfAbsent).
Луи Вассерман
15

Использование гуавы «s карт класса» служебные методы для вычисления разницы 2 карты вы можете сделать это в одной строке, с помощью метода подписи , что делает его более ясным , что вы пытаетесь достичь:

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());
}
Том Тресанский
источник
8

Просто повторите и добавьте:

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

Отредактируйте, чтобы добавить:

Если вы можете внести изменения в a, вы также можете:

a.putAll(b)

и у вас будет именно то, что вам нужно. (все записи в bи все записи a, которых нет b)

Преподобный Гонзо
источник
1.) entrySet()возвращает a Set<Map.Entry>. 2.) Нет метода contains(...)для java.util.Map.
Фабиан Барни
Нет ли более умного способа? Как утилита Collections или что-то в этом роде? Я ненавижу все циклы for повсюду.
rapadura
1
@AntonioP: Все циклы for везде? Есть один цикл for, и он настолько прост, насколько это возможно.
Преподобный Гонзо,
+1 Тогда, я думаю, просто работает, когда Карты используются не с необработанным шрифтом. Я немного запутался с Map.Entry :-)
Фабиан Барни
@Reverend Gonzo, а, в другом месте кода. :) Wont .putAll заменяет существующие ключи и значения a? Я пойду в этом смысле, это кажется наиболее простым путем.
rapadura
5

Вы можете сделать это всего в одной строке, если измените порядок карт в решении @ erickson:

mapWithNotSoImportantValues.putAll( mapWithImportantValues );

В этом случае вы заменяете значения в mapWithNotSoImportantValues ​​на значение из mapWithImportantValues ​​с теми же ключами.

Анатолий Степанюк
источник
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);
}}
Джаджикантх Пидимарла
источник
2

В Java 8 есть этот метод API для выполнения ваших требований.

map.putIfAbsent(key, value)

Если указанный ключ еще не связан со значением (или сопоставлен с нулевым значением), связывает его с заданным значением и возвращает null, иначе возвращает текущее значение.

новый день
источник
1
мы можем поставить AllIfAbsent? это то что мне нужно ?
user1735921
0

Как говорили другие, вы можете использовать putIfAbsent. Выполните итерации по каждой записи на карте, которую вы хотите вставить, и вызовите этот метод на исходной карте:

mapToInsert.forEach(originalMap::putIfAbsent);
свистящий сурок
источник