4

How can I create a map that can extend its list of value. For example I have a map which contains: key A and list of values B {1,2,3}. Then at some point during the program running, I would like to add more value, ex: 4 to list B. Now my new map should be something like: (A,{1,2,3,4}). How can I do that?

5
  • 2
    map.get("A").add(4); Commented May 29, 2017 at 11:51
  • @QBrute this won't work as when you print the map it just prints the latest entry which in your case is 4, but not 1,2,3,4 like the questions asks. Commented Oct 2, 2019 at 7:11
  • @war_Hero that doesn't make sense, have you tried it? Of course you get the map with the complete list and not just the latest entry when you print it. Commented Oct 2, 2019 at 7:35
  • Lol, dude read the docs or even refer to answer below, they are using a list to store the values, as for a map it's only one key one value, it's a common gotcha unless you have tired it in code, wanted to call it out as it should not mislead others. Commented Oct 2, 2019 at 7:38
  • If you have a container like Map that holds a reference to a List and then you fetch that list and change it around then that change will be visible in the map. You don't replace the value of the map, you update it. That list is the value. If you have a map {A=[1, 2, 3]} and then you do map.get("A") you hold the reference to the list [1,2,3]. Then you do .add(4) on that same list. If you print out the map afterwards you will see {A=[1, 2, 3, 4]} because you're working with references! Please get your facts straight before calling me out on a completely wrong basis. Commented Oct 2, 2019 at 7:50

6 Answers 6

14

Since Map<K,V> maps one key to one value, you need V to be of type List<T>:

Map<String,List<Integer>> multiMap = new HashMap<>();

One consequence of having a type like that is that now the process of adding an item to a key consists of two steps: you must check if the list for the key exists, and then either add a new item to an existing list, or add a new list with a single item:

List<Integer> current = multiMap.get(key);
if (current == null) {
    current = new ArrayList<Integer>();
    multiMap.put(key, current);
}
current.add(val);

If you use Java 8, you can use computeIfAbsent to greatly simplify the code:

multiMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
Sign up to request clarification or add additional context in comments.

3 Comments

You can simplify the implementation by using the newer computeIfAbsent method: multiMap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
@MalteHartwig Right, Java 8 added this convenient option, which greatly improves readability of the operation. Thank you!
@MalteHartwig: wow thank you! this look great and more professional with Java 8!
3

Such type of collection already implemented. Take a look at Multimap from Guava. Don't invent the bike from the scratch.

Hope it helps!

Comments

3

Add new Integer using new temp variable, Check with this explains might be help.

    Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
    List<Integer> list = new ArrayList<Integer>();
    list.add(1);
    list.add(2);
    list.add(3);

    map.put("A", list);
    map.forEach((key,value)->System.out.print(key + " : "+
    value));
    List<Integer> newList = (ArrayList<Integer>)map.get("A");
    newList.add(4);
    System.out.println();
    map.put("A", newList);
    map.forEach((key,value)->System.out.print(key + " : "+
            value));

Comments

1

A more generic solution is to have a MultiMap class which provides any Collection type as value e.g. ArrayList: I found this in a Java-Book weeks ago. Example:

class MultiMap<K, V> 
{
  private final Map<K,Collection<V>> map = new HashMap<>();

  public Collection<V> get(K key) 
  {
    return map.getOrDefault(key, Collections.<V> emptyList());
  }
  public void put(K key,V value )
  {
    map.computeIfAbsent( key, k -> new ArrayList<>()).add( value );
  }
}

Usage may be: (the map value is a ArrayList of Strings)

MultiMap<Integer,String> map = new MultiMap<>();
int id = 34;
System.out.println(map.get(id)); // creates an ArrayList<String> for key 34

map.put(id,"first value for 34");
System.out.println(map.get(id)); // [first value for 34]

map.put(id,"second");
System.out.println(map.get(id)); // [first value for 34, second]

Hope this helps...

Comments

0
 public static void main(String[] args) {

Map<String, List<String>> map = new HashMap<String, List<String>>();

List<String> valSetOne = new ArrayList<String>();
valSetOne.add("ABC");
valSetOne.add("BCD");
valSetOne.add("DEF");

List<String> valSetTwo = new ArrayList<String>();
valSetTwo.add("CBA");
valSetTwo.add("DCB");

map.put("FirstKey", valSetOne);
map.put("SecondKey", valSetTwo);

for (Map.Entry<String, List<String>> entry : map.entrySet()) {

    String key = entry.getKey();

    List<String> values = entry.getValue();

    System.out.println("Value of " + key + " is " + values);

}

}

You can use Set or List based on your requirement.This is a simple method of having single key with multiple values.

Comments

0

Java 8. Stream API.

For example we have collection of Users as List:

[{ name: "qwer", surname: "asdf", type: "premium"}, { name: "ioup", surname: "vmnv", type: "usual"}, { name: "rtyr", surname: "zxc", type: "premium"}] 

and we need to add multiple Users to Map where key is «type»

Map<String, List<User>> map = collection.stream().collect(Collectors.groupingBy(User::getType, Collectors.mapping(Function.identity(), Collectors.toList())))

To process this map we can make new stream

map.entrySet().stream().{map|reduce|& other things}...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.