Як поставити весь на Java вміст hashMap одного до іншого, але не замінити існуючі ключі та значення?


83

Мені потрібно скопіювати всі ключі та значення з одного HashMap A на інший B, але не замінювати існуючі ключі та значення.

Що найкращий спосіб зробити це?

Я думав замість цього повторити keySet і checkig, якщо він існує чи ні, я б

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

Привіт! Чому mapWithValues.putAll (mapWithAnotherValues) не працює?
betomoretti

15
@erickson набагато більш компактною версією Java 8: patch.forEach(target::putIfAbsent).
Луїс Вассерман

15

Використовуючи утилітні методи Guava ' Maps Maps ' для обчислення різниці між двома картами, ви можете зробити це в один рядок, з підписом методу, що робить більш зрозумілим, що ви намагаєтесь досягти:

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 скрізь.
рападура

1
@AntonioP: Усі петлі for скрізь? Є один для циклу, і це приблизно так само просто, як ви можете отримати.
Преподобний Гонзо

Потім +1, просто працює, коли Карти використовуються не з необробленим типом, я думаю. Захопився трохи з картою. Вхід :-)
Фабіан Барні

@ Преподобний Гонзо, ах, в іншому місці коду. :) Не буду .putВсі замінювати існуючі ключі та значення a? Я погано піду з цим почуттям, але це видається найпростішим способом.
рападура

5

Ви можете зробити це всього в 1 рядок, якщо змінити порядок карт у рішенні @ 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? ось що мені потрібно?
користувач1735921

0

Як казали інші, ви можете використовувати putIfAbsent. Переглядайте кожен запис на карті, який потрібно вставити, і використовуйте цей метод на вихідній карті:

mapToInsert.forEach(originalMap::putIfAbsent);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.