2016-11-25 2 views
2

У меня есть два HashMaps, где ключ - это String, а value - ArrayList. Мне нужно объединить эти две карты таким образом, что если -Слияние двух карт <String,List>

  1. Если ключ уже не существует, ключ должен отображаться с заданным значением.
  2. Если ключ уже присутствует, я хочу, чтобы существующее значение было объединено с новым значением, то есть существующимList.addAll (newList).

исходный код несколько похож -

для всех ключей проверки карты, если

if (map1.containsKey("key")){ 
List l = map1.get ("key"); 
l.addAll(map2.get("key")); 
} 
else{ 
map1.put(map2); 
} 

Я не забочусь о дублирующих элементов здесь. Есть ли чистый способ сделать это? Я прочитал о методе слияния, представленном в Java 8. Но поскольку значения здесь имеют тип List, я ищу более эффективный и чистый способ.

+3

Я бы предложил просто написать его точно так, как вы его описали. Затем вы всегда можете его реорганизовать. – f1sh

+2

Можете добавить код своей первой попытки? Исходя из этого, будет намного легче обсуждать чистоту и эффективность. – reto

+2

Я не уверен, что вы имеете в виду «* Мне не нужны дублирующие элементы здесь *». Кроме того, кажется, что «слияние» - это путь, то есть «map2.forEach ((k, v) -> map1.merge (k, v, (l1, l2) -> {l1.addAll (l2); return l1;})); ' – Holger

ответ

1

Надеюсь, что этот код поможет. Вы должны перебрать один из списков и добавить или обновить другой список.

public static HashMap<String, ArrayList<Object>> merge(HashMap<String, ArrayList<Object>> list_1, HashMap<String, ArrayList<Object>> list_2) { 
    //Iterate second hash map 
    Iterator it = list_2.entrySet().iterator(); 
    while (it.hasNext()) { 
     Map.Entry pair = (Map.Entry) it.next(); 
     String key = (String) pair.getKey(); 
     ArrayList<Object> value = (ArrayList<Object>) pair.getValue(); 
     if(list_1.containsKey(key)){ 
      //UPDATE 
      list_1.replace(key, value); //Replaces the entry for the specified key only if it is currently mapped to some value. 
     } else { 
      //ADD 
      list_1.put(key, value); 
     } 
    } 
    return list_1; 
} 
1

Ваше решение будет гораздо более удобным для чтения, если переключиться с Map<String, ArrayList> в guava «s Multimap

Тогда слияние может быть сделано с putAll

multimap.putAll(secondMultimap); 
+0

putAll() также возможно с помощью Java-карт, но не будет putAll() заменить значение, если ключ уже существует? – raghav

0

Вот подход, использующий Map.merge java8 в()

//your two input maps 
Map<String, List<String>> input1 = new HashMap<>(); 
Map<String, List<String>> input2 = new HashMap<>(); 
Map<String, List<String>>[] arrr = new Map[]{input1,input2}; 

Map<String, List<String>> merged = new HashMap<>(); 
for(Map<String, List<String>> input:arrr){ 
    for(Entry<String, List<String>> e:input.entrySet()){ 
    merged.merge(e.getKey(), e.getValue(), (v1,v2)->{v1.addAll(v2);return v1;}); 
    } 
} 

Это создает один экземпляр карты как вывод (merged). Я не тестировал это, поэтому я не уверен, что внутренняя работа merge вызывает v1 в null в какой-то момент.

+0

Не хотите иметь третью карту, но объединить ее с другой. Спасибо, попытаюсь изменить это. – raghav

+0

Кроме того, вложенные для петель не будут слишком хорошо проходить. – raghav

+0

@raghav внешний цикл повторяется ровно дважды, так как у вас есть 2 входных карты. И поскольку ключи могут отличаться между этими картами, вам нужно объединиться с обоими. Так как же это не хорошая идея? – f1sh

Смежные вопросы