开发者

Appending data to Map in Java

I have a Map

Map<Integer, List<Object>> entireData;

Now to this I'm adding some data using putAll like

entireData.putAll(someData);
开发者_如何学JAVA

where someData returns Map<Integer, List<Object>>

Now, I have another line which says

entireData.putAll(someMoreData);

which also returns Map<Integer, List<Object>>, but by doing this it over-writes the content of the existing entireData, how do I append?


First line of the Java Map Class Reference:

An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.


You want a Multimap from Google Guava. Rewriting your example with Guava Multimap:

ListMultimap<Integer, Object> entireData = ArrayListMultimap.create();

entireData.get(key) returns a List<Object>. putAll will not override old keys but will append the values of those keys to the existing values. This is also much nicer than dealing with initializing the List instances yourself.


for (Integer key : someMoreData.keySet())
{
    if (entireData.containsKey(key))
    {
        entireData.get(key).addAll(someMoreData.get(key));
    }
    else
    {
        entireData.put(key, someMoreData.get(key));
    }
}


Keys are unique. If someMoreData has a key same as already existing key in entireData the value i.e. list of object will be overwritten.

However you can loop in someMoreData and append for keys that exists in entireData like

 for(Integer key: someMoreData.keySet()){
       if(entireData.get(key)!=null)
           entireData.get(key).addAll(someMoreData.get(key));
       else
           entireData.put(key,someMoreData.get(key));
 }


Per default, Java Maps map one key to one value, as trojanfoe writes. If that is not sufficient to your needs, you need a Multi-Map implementation (A Map that maps from a key to a collection of values).

The most popular versions can be found in two open source Frameworks, Google Guava and Apache Commons / Collections.

Guava Example:

final Multimap<Integer, String> mmap =
    Multimaps.newSetMultimap(
        Maps.<Integer, Collection<String>> newHashMap(),
        new Supplier<Set<String>>(){

            @Override
            public Set<String> get(){
                return Sets.newHashSet();
            }
        });
mmap.put(1, "foo");
mmap.put(1, "bar");
System.out.println(mmap.get(1));

Output:

[foo, bar]

Commons Collections Example:

final MultiMap mmap = new MultiHashMap();
mmap.put(1, "foo");
mmap.put(1, "bar");
System.out.println(mmap.get(1));

Output:

[foo, bar]

As you can see, the Commons Collections version is a lot simpler, but it's also less powerful, and in the current version it doesn't support Java 1.5 generics. So I'd go with Guava.


similar to willcodejavaforfood's no dependencies needed answer but using an entrySet instead for less HashMap retrievals.

public static <K,V> void appendMapBtoMapA(HashMap<K,List<V>> a, HashMap<K,List<V>> b) {
    for (Map.Entry<K, List<V>> bEntry : b.entrySet()) {
        if (a.containsKey(bEntry.getKey())) {
            a.get(bEntry.getKey()).addAll(bEntry.getValue());
        } else {
            a.put(bEntry.getKey(), bEntry.getValue());
        }
    }
}

or Nishant's which drops a contains call and adds a null check but with entrySet

public static <K,V> void appendMapBtoMapA(HashMap<K,List<V>> a, HashMap<K,List<V>> b) {
    for (Map.Entry<K, List<V>> bEntry : b.entrySet()) {
        List<V> aValue = a.get(bEntry.getKey());
        if (aValue != null) {
            aValue.addAll(bEntry.getValue());
        } else {
            a.put(bEntry.getKey(), bEntry.getValue());
        }
    }
}

or with java 8

public static <K,V> void appendMapBtoMapA(HashMap<K,List<V>> a, HashMap<K,List<V>> b) {
    for (Map.Entry<K, List<V>> bEntry : b.entrySet()) {
        a.computeIfAbsent(
            bEntry.getKey(), 
            k -> new LinkedList<>()
        ).addAll(bEntry.getValue());
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜