Java: объединить два хеш-карты? - PullRequest
0 голосов
/ 22 мая 2018

Я пытался реализовать свою собственную функцию слияния, но она становится все более и более сложной и имеет все больше и больше ошибок.Я думал, может быть, у Java уже есть эта функция, так как это кажется общей проблемой разработки.

Представьте, что у меня есть два HashMaps<String, int>:

 HM1.put(foo,1)
 HM1.put(bar,1)

 HM2.put(foo,1)
 HM2.put(main,1)

Когда они объединены, новый HM2 будетбыть примерно таким:

 [foo: 2]
 [bar, 1]
 [main,1]

Ответы [ 5 ]

0 голосов
/ 20 августа 2019

Еще один способ сделать это - использовать toMap Collector , который определен для использования функции слияния:

var hm1 = new HashMap<String, Integer>();
hm1.put("foo",1);
hm1.put("bar",2);
var hm2 = new HashMap<String, Integer>();
hm2.put("foo",4);
hm2.put("baz",8);
var v = Stream.of(hm1, hm2)
    .map(Map::entrySet)
    .flatMap(Set::stream)
    .collect(
        Collectors.toMap(
            Map.Entry::getKey,   // key mapper
            Map.Entry::getValue, // value mapper
            Integer::sum         // merge function
        )
    );
System.out.println(v);

Выход:

{bar = 2, foo = 5, baz = 8}

0 голосов
/ 20 августа 2019

Map.merge(), как указано выше, неверно.Функция переотображения должна быть

(oldvalue, newvalue) -> oldvalue + newvalue

Интересно, что оригинальный автор ошибочно принял 2 * 1, как он реализовал, за 1 + 1.Эй, результат - то, что я хочу, верно?Извлеченный урок: 1 не является хорошим значением теста.

0 голосов
/ 22 мая 2018

Вы можете перебрать вторую карту и динамически обновить HM1:

HM2.entrySet()
   .forEach(entry -> HM1.compute(
            entry.getKey(),
            (key, value) -> value == null ? 
                            entry.getValue() : 
                            entry.getValue() + value));

EDIT :Лучше использовать .merge (предложено lexicore в в этом комментарии ), что позволяет избежать ненужных запусков функции вычисления для отсутствующих ключей:

HM2.entrySet()
   .forEach(entry -> HM1.merge(
            entry.getKey(),
            entry.getValue(),
            (key, value) -> entry.getValue()   + value));

Любое из вышеперечисленных обновит HM1чтобы получить окончательный результат.

System.out.println(HM1);

Выход:

{bar=1, foo=2, main=1}
0 голосов
/ 22 мая 2018

Вот решение на основе потока / коллектора.Он превращает карты в потоки записей, объединяет их и затем собирает в карту, используя ключи входа в качестве ключей и суммируя значения как int s.

    Map<String, Integer> HM1 = new HashMap<>();
    Map<String, Integer> HM2 = new HashMap<>();
    HM1.put("foo", 1);
    HM1.put("bar", 1);

    HM2.put("foo", 1);
    HM2.put("main", 1);

    Map<String, Integer> result = Stream
        .concat(HM1.entrySet().stream(), HM2.entrySet().stream())
        .collect(
                Collectors.groupingBy(
                        Map.Entry::getKey,
                        Collectors.summingInt(Map.Entry::getValue)));
0 голосов
/ 22 мая 2018

надеюсь, это вам поможет

Set<String> keySet=hashMap1.keySet();

for(String str: keySet){
    int value=hashMap1.get(str);
    if(hashMap2.containsKey(str)){
        hashMap2.put(str, hashMap2.get(str)+value);
    }
    else{
        hashMap2.put(str, value);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...