Looking for a standard library function way in Java for adding the values in two maps based on their keys.
Map A: {a=1, b=2}
Map B: {a=2, c=3}
Resulting map:
Map C: {a=3, b=2, c=3}
I know this can be coded in a few lines. I also know functional programming is great for this. I am just wandering if there is a standard function or syntax people use out there.
Something like (but probably more generic than):
public HashMap<String,Double> addValues(HashMap<String,Double> a, HashMap<String,Double> b) {
HashMap<String,Double> ret = new HashMap<String,Double>(a);
for (String s : b.keySet()) {
if (ret.containsKey(s)) {
ret.put(s, b.get(s) + ret.get(s));
} else {
ret.put(s, b.get(s));
}
}
return ret;
}
An alternative which does essentially the same thing, using Java 8 new getOrDefault method:
Set<String> keys = new HashSet<> (a.keySet());
keys.addAll(b.keySet());
Map<String, Integer> c = new HashMap<>();
for (String k : keys) {
c.put(k, a.getOrDefault(k, 0) + b.getOrDefault(k, 0));
}
But if using Java 8, you may as well stream the keys and make it a one liner:
Map<String, Object> c = Stream.concat(a.keySet().stream(), b.keySet().stream())
.distinct()
.collect(toMap(k -> k, k -> a.getOrDefault(k, 0) + b.getOrDefault(k, 0)));
I think what you are doing is just fine. I can think of one other way though, using a MultiMap. You can add all your elements to a multimap and then run a summation function over all the values for each key at the end.
Here's a version that allows for any number of Maps to be combined:
public static Map<String, Integer> addKeys(Map<String, Integer>... maps) {
Set<String> keys = new HashSet<String>();
for (Map<String, Integer> map : maps)
keys.addAll(map.keySet());
Map<String, Integer> result = new HashMap<String, Integer>();
for (String key : keys) {
Integer value = 0;
for (Map<String, Integer> map : maps)
if (map.containsKey(key))
value += map.get(key);
result.put(key, value);
}
return result;
}
Usage:
public static void main(String[] args){
Map<String, Integer> a = new HashMap<String, Integer>();
a.put("a", 1);
a.put("b", 2);
Map<String, Integer> b = new HashMap<String, Integer>();
b.put("a", 2);
b.put("c", 3);
Map<String, Integer> c = addKeys(a, b);
System.out.println(c);
}
Ouptut:
{b=2, c=3, a=3}
Unfortunately, it's not possible as far as I can see to create a generic method:
public static <K, V extends Number> Map<K, V> addKeys(Class<V> cls, Map<K, V>... maps);
Because the Number class doesn't support the + operator. Which seems a bit daft to me...
I want to create a nested HashMap that will take two keys of type float and give out value of type Integer.
public static HashMap<Float, HashMap<Float, Integer>> hashX = new HashMap<Float,HashMap<Float, Integer>>();
Is there a simple method of putting/getting the values like an ordinary HashMap i.e.
hashX.put(key, value);
hashX.get(key);
or is it a more complicated method that must be used?
I have searched around the web for a solution but am finding it tough to find a solution that applies to me. Any help would be appreciated!
Map<Float, Map<Float, Integer>> map = new HashMap<>();
map.put(.0F, new HashMap(){{put(.0F,0);}});
map.put(.1F, new HashMap(){{put(.1F,1);}});
map.get(.0F).get(.0F);
You have to get() the nested map out of the outer map and call can call put() and get() on it
float x = 1.0F;
HashMap<Float, Integer> innerMap = hashX.get(x);
if (innerMap == null) {
hashX.put(x, innerMap = new HashMap<>()); // Java version >= 1.7
}
innerMap.put(2.0F, 5);
You can create a wrapper class with a method like this:
public class MyWrapper {
private Map<Float, Map<Float, Integer>> hashX;
// ...
public void doublePut(Float one, Float two, Integer value) {
if (hashX.get(one) == null) {
hashX.put(one, new HashMap<Float, Integer>());
}
hashX.get(one).put(two, value);
}
}
Please note that you should use interfaces instead of concrete implementations when you declare your fields. For example it would make easier to refactor HashMap into ConcurrentHashMap if the need arises.
You can do it like this:
HashMap<Float, Integer> h1 = new HashMap<Float, Integer>();
h1.put(1.0f,new Integer(1));
HashMap<Float, Integer> h2 = new HashMap<Float, Integer>();
h2.put(3.0f,new Integer(3));
hashX.put(1.0f, h1);
hashX.put(1.0f, h1);
Try this.
static <K0, K1, V> void put(Map<K0, Map<K1, V>> map, K0 k0, K1 k1, V value) {
map.computeIfAbsent(k0, x -> new HashMap<>()).put(k1, value);
}
static <K0, K1, V> V get(Map<K0, Map<K1, V>> map, K0 k0, K1 k1) {
return Optional.ofNullable(map.get(k0)).map(s -> s.get(k1)).orElse(null);
}
and
Map<Float, Map<Float, Float>> map = new HashMap<>();
put(map, 1F, 2F, 3F);
put(map, 4F, 5F, 6F);
System.out.println(map);
output:
{4.0={5.0=6.0}, 1.0={2.0=3.0}}
Or simply
Map<Float, Map<Float, Float>> map = Map.of(
1F, Map.of(2F, 3F),
4F, Map.of(5F, 6F));
I want to create a nested HashMap that will take two keys of type float and give out value of type Integer.
You don't need a nested Map for that. If you want to lookup using a composite key, it is better to declare your map to be as such. There isn't a good Pair class in JFK, but you ca use Map.Entry, which is somewhat inconvenient to use but works:
Map<Map<Float, Float>, Integer> map = new ....
See https://stackoverflow.com/a/3110563/18573 for creating Map.Entry instances
package com.Collection;
import java.util.*;
public class India {
public static void main(String[] args) {
Set s = new TreeSet();
s.add("Barshi");
s.add("Pandharpur");
s.add("Kurduwadi");
s.add("Vairag");
Map<String,Map<String,Map<String,TreeSet>>> map =
Map.of("India", Map.of("Maharashtra", Map.of("Solapur", new TreeSet(s))));
System.out.println(map);
System.out.println(map.get("India").get("Maharashtra").get("Solapur").contains("Barshi"));
}
}
I have two maps whose keys are Strings and whose values are Set<MyObject>. Given two Maps, what is the easiest way to merge them such that if two keys are identical, the value is a union of the two sets. You can assume values are never null and if it is useful, we can make these Maps SortedMaps.
You can do this with a stream fairly easily:
Map<T, Set<U>> merged = Stream.of(first, second)
.map(Map::entrySet)
.flatMap(Set::stream)
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> {
HashSet<U> both = new HashSet<>(a);
both.addAll(b);
return both;
}));
This splits the maps into their Entrys and then joins them with a Collector which resolves duplicates by adding both values to a new HashSet.
This also works for any number of maps.
Some variations which produce the same result:
Stream.of(first, second).flatMap(m -> m.entrySet().stream())
.collect(...);
Stream.concat(first.entrySet().stream(), second.entrySet().stream())
.collect(...); //from comment by Aleksandr Dubinsky
The third parameter for Collectors.toMap is not necessary if there are no duplicate keys.
There is another Collectors.toMap with a fourth parameter that lets you decide the type of the Map collected into.
Are we talking about HashMap instances. In that case lookup is O(1), so you can just take one map, iterate over the entries of that map, see whether the other map contains that key. If not, just add the set. If it contains the key, take the union of the two sets (by adding all elements of one set to another)
To illustrate with some code, where I used a Set to have autocompletion in my IDE
Map<String, Set<Double>> firstMap = new HashMap<String, Set<Double>>( );
Map<String, Set<Double>> secondMap = new HashMap<String, Set<Double>>( );
Set<Map.Entry<String, Set<Double>>> entries = firstMap.entrySet();
for ( Map.Entry<String, Set<Double>> entry : entries ) {
Set<Double> secondMapValue = secondMap.get( entry.getKey() );
if ( secondMapValue == null ) {
secondMap.put( entry.getKey(), entry.getValue() );
}
else {
secondMapValue.addAll( entry.getValue() );
}
}
static void mergeSet(Map<String, Set<String>> map1, Map<String, Set<String>> map2) {
map1.forEach((key1, value1) -> {
map2.merge(key1, value1, (key2, value2) -> key2).addAll(value1);
});
}
How about this (untested):
Map<String,Set<Whatever>> m1 = // input map
Map<String,Set<Whatever>> m2 = // input map
Map<String,Set<Whatever>> ret = // new empty map
ret.putAll(m1);
for(String key : m2.keySet()) {
if(ret.containsKey(key)) {
ret.get(key).addAll(m2.get(key));
} else {
ret.put(key,m2.get(key));
}
}
This solution doesn't modify the input maps, and because it is short and relies on API methods only, I find it quite readable.
Note that putAll() and addAll() are both optional methods in Map and Set. Consequently (and in order to get O(1) lookup), I'd recommend using HashMap and HashSet.
Note that because neither HashSet or HashMap are synchronised you will need to look for some other solution if you want thread-safe code.
The following should merge a map1 into map2 (untested):
for (Entry<String, Set<???>> entry : map1.entrySet( ))
{
Set<???> otherSet = map2.get(entry.getKey( ));
if (otherSet == null)
map2.put(entry.getKey( ), entry.getValue ( ));
else
otherSet.addAll(entry.getValue( ));
}
I don't know what you've parameterized your Sets on, hence the <???>: replace as appropriate.
Something like this (untested):
// Assume all maps are of the same generic type.
public static Map<String, Set<MyObject>> mergeAll(Map m1, Map m2) {
Map<String, Set<MyObject>> merged = new HashMap();
// Merge commom entries into the new map.
for (Map.Entry<String, Set<MyObject>> entry : m1.entrySet()) {
String key = entry.getKey();
Set<MyObject> s1 = new HashSet(entry.getValue());
Set<MyObject> s2 = m2.get(key);
if (s2 != null) s1.addAll(s2);
merged.put(key, s1);
}
// Add entries unique to m2 to the new map.
for (String key : m2.keys()) {
if (!s1.containsKey(key)) merged.put(key, new HashSet(m2.get(key)));
}
return merged;
}
Note that this solution does not mutate either of its arguments.
Map<Integer,String> m1=new HashMap<Integer,String>();
Map<Integer,String> m2=new HashMap<Integer,String>();
m1.put(1,"one");
m1.put(2,"two");
m2.put(3,"three");
m2.put(2,"two");
Set<Integer> s=m2.keySet();
for(int i:s){
if(m1.get(i)==null){
m1.put(i,m2.get(i));
}
}
System.out.println(m1);
Note that all other answers will eventually augment the original sets which you might not want for all use cases, if you don't want that just use a third map as output and create a new set for each key
public static void merge2Maps(Map<String, Set<Double>> a, Map<String, Set<Double>> b, Map<String, Set<Double>> c){
for (Map.Entry<String, Set<Double>> entry : a.entrySet()) {
Set<Double> set = new HashSet<Double>();
c.put(entry.getKey(), set);
set.addAll(entry.getValue());
}
for (Map.Entry<String, Set<Double>> entry : b.entrySet()) {
String key = entry.getKey();
Set<Double> set = c.get(key);
if (set == null) {
set = new HashSet<Double>();
c.put(entry.getKey(), set);
}
set.addAll(entry.getValue());
}
}
If you want to end up with immutable data structures to prevent manipulation of your merged map and map's Set instances then you can take this approach. This solution uses Google's Guava library.
public <K,T> Map<K, Set<T>> mergeToImmutable (
final Map<K, Set<T>> left,
final Map<K, Set<T>> right)
{
return Maps.toMap(
Sets.union(
checkNotNull(left).keySet(),
checkNotNull(right).keySet()
),
new Function<K, Set<T>> () {
#Override
public Set<T> apply (K input) {
return ImmutableSet.<T>builder()
.addAll(MoreObjects.firstNonNull(left.get(input), Collections.<T>emptySet()))
.addAll(MoreObjects.firstNonNull(right.get(input), Collections.<T>emptySet()))
.build();
}
}
);
}
If you define a method to unite non-null Sets as:
static <T> Set<T> union(Set<T>... sets) {
return Stream.of(sets)
.filter(s -> s != null)
.flatMap(Set::stream)
.collect(Collectors.toSet());
}
then merging two maps m1 and m2 having Set<V> values can be performed as follows:
Map<String, V> merged
= union(m1.keySet(), m2.keySet())
.stream()
.collect(Collectors.toMap(k -> k, k -> union(m1.get(k), m2.get(k))));
Or even simpler:
Map<String, V> merged = new HashMap<>();
for (String k : union(m1.keySet(), m2.keySet())
merged.put(k, union(m1.get(k), m2.get(k)));
<K, V> Map<K, List<V>> mergeMapOfLists(Stream<Map<K, List<V>>> stream) {
return stream
.map(Map::entrySet) // convert each map to set of map's entries
.flatMap(Collection::stream) // convert each map entry to stream and flat them to one stream
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue,
(list1, list2) -> {
list1.addAll(list2);
return list1;
})); // convert stream to map; if key is duplicated execute merge fuction (append exisitng list with elements from new list)
}
I have two HashMap objects defined like so:
HashMap<String, Integer> map1 = new HashMap<String, Integer>();
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
I also have a third HashMap object:
HashMap<String, Integer> map3;
How can I merge map1 and map2 together into map3?
map3 = new HashMap<>();
map3.putAll(map1);
map3.putAll(map2);
If you know you don't have duplicate keys, or you want values in map2 to overwrite values from map1 for duplicate keys, you can just write
map3 = new HashMap<>(map1);
map3.putAll(map2);
If you need more control over how values are combined, you can use Map.merge, added in Java 8, which uses a user-provided BiFunction to merge values for duplicate keys. merge operates on individual keys and values, so you'll need to use a loop or Map.forEach. Here we concatenate strings for duplicate keys:
map3 = new HashMap<>(map1);
for (Map.Entry<String, String> e : map2.entrySet())
map3.merge(e.getKey(), e.getValue(), String::concat);
//or instead of the above loop
map2.forEach((k, v) -> map3.merge(k, v, String::concat));
If you know you don't have duplicate keys and want to enforce it, you can use a merge function that throws an AssertionError:
map2.forEach((k, v) ->
map3.merge(k, v, (v1, v2) ->
{throw new AssertionError("duplicate values for key: "+k);}));
Taking a step back from this specific question, the Java 8 streams library provides toMap and groupingBy Collectors. If you're repeatedly merging maps in a loop, you may be able to restructure your computation to use streams, which can both clarify your code and enable easy parallelism using a parallel stream and concurrent collector.
One-liner using Java 8 Stream API:
map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue))
Among the benefits of this method is ability to pass a merge function, which will deal with values that have the same key, for example:
map3 = Stream.of(map1, map2).flatMap(m -> m.entrySet().stream())
.collect(Collectors.toMap(Entry::getKey, Entry::getValue, Math::max))
Java 8 alternative one-liner for merging two maps:
defaultMap.forEach((k, v) -> destMap.putIfAbsent(k, v));
The same with method reference:
defaultMap.forEach(destMap::putIfAbsent);
Or idemponent for original maps solution with third map:
Map<String, Integer> map3 = new HashMap<String, Integer>(map2);
map1.forEach(map3::putIfAbsent);
And here is a way to merge two maps into fast immutable one with Guava that does least possible intermediate copy operations:
ImmutableMap.Builder<String, Integer> builder = ImmutableMap.<String, Integer>builder();
builder.putAll(map1);
map2.forEach((k, v) -> {if (!map1.containsKey(k)) builder.put(k, v);});
ImmutableMap<String, Integer> map3 = builder.build();
See also Merge two maps with Java 8 for cases when values present in both maps need to be combined with mapping function.
If you don't need mutability for your final map, there is Guava's ImmutableMap with its Builder and putAll method which, in contrast to Java's Map interface method, can be chained.
Example of use:
Map<String, Integer> mergeMyTwoMaps(Map<String, Integer> map1, Map<String, Integer> map2) {
return ImmutableMap.<String, Integer>builder()
.putAll(map1)
.putAll(map2)
.build();
}
Of course, this method can be more generic, use varargs and loop to putAll Maps from arguments etc. but I wanted to show a concept.
Also, ImmutableMap and its Builder have few limitations (or maybe features?):
they are null hostile (throw NullPointerException - if any key or value in map is null)
Builder don't accept duplicate keys (throws IllegalArgumentException if duplicate keys were added).
HashMap has a putAll method.
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
You could use Collection.addAll() for other types, e.g. List, Set, etc. For Map, you can use putAll.
Generic solution for combining two maps which can possibly share common keys:
In-place:
public static <K, V> void mergeInPlace(Map<K, V> map1, Map<K, V> map2,
BinaryOperator<V> combiner) {
map2.forEach((k, v) -> map1.merge(k, v, combiner::apply));
}
Returning a new map:
public static <K, V> Map<K, V> merge(Map<K, V> map1, Map<K, V> map2,
BinaryOperator<V> combiner) {
Map<K, V> map3 = new HashMap<>(map1);
map2.forEach((k, v) -> map3.merge(k, v, combiner::apply));
return map3;
}
Very late but let me share what I did when I had the same issue.
Map<String, List<String>> map1 = new HashMap<>();
map1.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map1.put("NZ", Arrays.asList("P1","P2","P3"));
Map<String, List<String>> map2 = new HashMap<>();
map2.put("India", Arrays.asList("Virat", "Mahi", "Rohit"));
map2.put("NZ", Arrays.asList("P1","P2","P4"));
Map<String, List<String>> collect4 = Stream.of(map1, map2)
.flatMap(map -> map.entrySet().stream())
.collect(
Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(strings, strings2) -> {
List<String> newList = new ArrayList<>();
newList.addAll(strings);
newList.addAll(strings2);
return newList;
}
)
);
collect4.forEach((s, strings) -> System.out.println(s+"->"+strings));
It gives the following output
NZ->[P1, P2, P3, P1, P2, P4]
India->[Virat, Mahi, Rohit, Virat, Mahi, Rohit]
A small snippet I use very often to create map from other maps:
static public <K, V> Map<K, V> merge(Map<K, V>... args) {
final Map<K, V> buffer = new HashMap<>();
for (Map m : args) {
buffer.putAll(m);
}
return buffer;
}
you can use HashMap<String, List<Integer>> to merge both hashmaps and avoid losing elements paired with the same key.
HashMap<String, Integer> map1 = new HashMap<>();
HashMap<String, Integer> map2 = new HashMap<>();
map1.put("key1", 1);
map1.put("key2", 2);
map1.put("key3", 3);
map2.put("key1", 4);
map2.put("key2", 5);
map2.put("key3", 6);
HashMap<String, List<Integer>> map3 = new HashMap<>();
map1.forEach((str, num) -> map3.put(str, new ArrayList<>(Arrays.asList(num))));
//checking for each key if its already in the map, and if so, you just add the integer to the list paired with this key
for (Map.Entry<String, Integer> entry : map2.entrySet()) {
Integer value = entry.getValue();
String key = entry.getKey();
if (map3.containsKey(key)) {
map3.get(key).add(value);
} else {
map3.put(key, new ArrayList<>(Arrays.asList(value)));
}
}
map3.forEach((str, list) -> System.out.println("{" + str + ": " + list + "}"));
output:
{key1: [1, 4]}
{key2: [2, 5]}
{key3: [3, 6]}
You can use putAll function for Map as explained in the code below
HashMap<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("a", 1);
map1.put("b", 2);
map1.put("c", 3);
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
map1.put("aa", 11);
map1.put("bb", 12);
HashMap<String, Integer> map3 = new HashMap<String, Integer>();
map3.putAll(map1);
map3.putAll(map2);
map3.keySet().stream().forEach(System.out::println);
map3.values().stream().forEach(System.out::println);
Below snippet takes more than one map and combine them.
private static <K, V> Map<K, V> combineMaps(Map<K, V>... maps) {
if (maps == null || maps.length == 0) {
return Collections.EMPTY_MAP;
}
Map<K, V> result = new HashMap<>();
for (Map<K, V> map : maps) {
result.putAll(map);
}
return result;
}
Demo example link.
Assuming the following input:
import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.Map;
...
var m1 = Map.of("k1", 1, "k2", 2);
var m2 = Map.of("k3", 3, "k4", 4);
When you're sure not to have any key collisions between both input maps, a simple expression that avoids any mutations and yields an immutable result could be:
var merged = Stream.concat(
m1.entrySet().stream(),
m2.entrySet().stream()
).collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, Map.Entry::getValue));
In case key collisions are possible, we can provide a lambda to specify how to de-duplicate them. For example if we'd like to keep the largest value in case an entry is present in both input, we could:
.collect(Collectors.toUnmodifiableMap(
Map.Entry::getKey,
Map.Entry::getValue,
Math::max)) // any function (Integer, Integer) -> Integer is ok here
HashMap<Integer,String> hs1 = new HashMap<>();
hs1.put(1,"ram");
hs1.put(2,"sita");
hs1.put(3,"laxman");
hs1.put(4,"hanuman");
hs1.put(5,"geeta");
HashMap<Integer,String> hs2 = new HashMap<>();
hs2.put(5,"rat");
hs2.put(6,"lion");
hs2.put(7,"tiger");
hs2.put(8,"fish");
hs2.put(9,"hen");
HashMap<Integer,String> hs3 = new HashMap<>();//Map is which we add
hs3.putAll(hs1);
hs3.putAll(hs2);
System.out.println(" hs1 : " + hs1);
System.out.println(" hs2 : " + hs2);
System.out.println(" hs3 : " + hs3);
Duplicate items will not be added(that is duplicate keys) as when we will print hs3 we will get only one value for key 5 which will be last value added and it will be rat.
**[Set has a property of not allowing the duplicate key but values can be duplicate]
Method 1: Put maps in a List and then join
public class Test15 {
public static void main(String[] args) {
Map<String, List<String>> map1 = new HashMap<>();
map1.put("London", Arrays.asList("A", "B", "C"));
map1.put("Wales", Arrays.asList("P1", "P2", "P3"));
Map<String, List<String>> map2 = new HashMap<>();
map2.put("Calcutta", Arrays.asList("Protijayi", "Gina", "Gini"));
map2.put("London", Arrays.asList( "P4", "P5", "P6"));
map2.put("Wales", Arrays.asList( "P111", "P5555", "P677666"));
System.out.println(map1);System.out.println(map2);
// put the maps in an ArrayList
List<Map<String, List<String>>> maplist = new ArrayList<Map<String,List<String>>>();
maplist.add(map1);
maplist.add(map2);
/*
<T,K,U> Collector<T,?,Map<K,U>> toMap(
Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
*/
Map<String, List<String>> collect = maplist.stream()
.flatMap(ch -> ch.entrySet().stream())
.collect(
Collectors.toMap(
//keyMapper,
Entry::getKey,
//valueMapper
Entry::getValue,
// mergeFunction
(list_a,list_b) -> Stream.concat(list_a.stream(), list_b.stream()).collect(Collectors.toList())
));
System.out.println("Final Result(Map after join) => " + collect);
/*
{Wales=[P1, P2, P3], London=[A, B, C]}
{Calcutta=[Protijayi, Gina, Gini], Wales=[P111, P5555, P677666], London=[P4, P5, P6]}
Final Result(Map after join) => {Calcutta=[Protijayi, Gina, Gini], Wales=[P1, P2, P3, P111, P5555, P677666], London=[A, B, C, P4, P5, P6]}
*/
}//main
}
Method 2 : Normal Map merge
public class Test15 {
public static void main(String[] args) {
Map<String, List<String>> map1 = new HashMap<>();
map1.put("London", Arrays.asList("A", "B", "C"));
map1.put("Wales", Arrays.asList("P1", "P2", "P3"));
Map<String, List<String>> map2 = new HashMap<>();
map2.put("Calcutta", Arrays.asList("Protijayi", "Gina", "Gini"));
map2.put("London", Arrays.asList( "P4", "P5", "P6"));
map2.put("Wales", Arrays.asList( "P111", "P5555", "P677666"));
System.out.println(map1);System.out.println(map2);
/*
<T,K,U> Collector<T,?,Map<K,U>> toMap(
Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
*/
Map<String, List<String>> collect = Stream.of(map1,map2)
.flatMap(ch -> ch.entrySet().stream())
.collect(
Collectors.toMap(
//keyMapper,
Entry::getKey,
//valueMapper
Entry::getValue,
// mergeFunction
(list_a,list_b) -> Stream.concat(list_a.stream(), list_b.stream()).collect(Collectors.toList())
));
System.out.println("Final Result(Map after join) => " + collect);
/*
{Wales=[P1, P2, P3], London=[A, B, C]}
{Calcutta=[Protijayi, Gina, Gini], Wales=[P111, P5555, P677666], London=[P4, P5, P6]}
Final Result(Map after join) => {Calcutta=[Protijayi, Gina, Gini], Wales=[P1, P2, P3, P111, P5555, P677666], London=[A, B, C, P4, P5, P6]}
*/
}//main
}
In Python, HashMap is called Dictionary and we can merge them very easily.
x = {'Roopa': 1, 'Tabu': 2}
y = {'Roopi': 3, 'Soudipta': 4}
z = {**x,**y}
print(z)
{'Roopa': 1, 'Tabu': 2, 'Roopi': 3, 'Soudipta': 4}
you can use - addAll method
http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html
But there is always this issue that - if your two hash maps have any key same - then it will override the value of the key from first hash map with the value of the key from second hash map.
For being on safer side - change the key values - you can use prefix or suffix on the keys - ( different prefix/suffix for first hash map and different prefix/suffix for second hash map )