How do I add values to a Set inside a Map? [closed

2019-03-19 20:19发布

问题:

I have this map Map<String, Set<Integer>> myMap;, now I need to interact with it, how do I do it?


for example:

Keys are: "apple", "orange", "grape", etc.
Each set will contain random numbers: 1-9

I need to create a Map (HashMap or TreeMap) that has Strings for keys and sets for the values. I need to return the set given a key. I also need to be able to fill each set with multiple numbers based on a key. Not sure how to approach this problem. Any thoughts?

回答1:

Not difficult if I understand correctly.

Map<String, Set<Integer>> reqdMap = new HashMap<String, Set<Integer>>();

//Form the set corresponding to apple.
Set<Integer> appleSet = new HashSet<Integer>();
appleSet.add(1);
...


reqdMap.put("apple", appleSet);

//To Retrieve
appleSet = reqdMap.get("apple");


回答2:

Something to keep in mind is that the value will initially be null, so the first time you use a key, you'll have to initialize it:

Map<String,Set<Integer>> map;  

To add a number to the key, you must do this:

String key = "apple"; // for example 

Set<Integer> set = map.get(key); 
if (set == null) {
    set = new HashSet<Integer>();
    map.put(key, set);
}
set.add(5);

Unfortunately, everywhere you interact with the set, you must null check. For example, if you want to check if a certain key had a certain number mapped to it, you couldn't safely do this:

if (map.get(key).contains(number))  // not safe

because the call to get() may return null (if there's no entry for the key) and you'd get a NullPointerException.

There is a way to make your map very convenient to use by internalising the null check inside the map, so that a call to get() will always return a non-null set; create an anonymous class that overrides get() accordingly:

Map<String,Set<Integer>> map = new HashMap<String,Set<Integer>> () {
    @Override
    public Set<Integer> get(Object key) {
        Set<Integer> set = super.get(key); 
        if (set == null) {
            set = new HashSet<Integer>();
            put(key, set);
        }
        return set;
    }
}

With this in place, your main code becomes a lot simpler and clearer. To add:

map.get(key).add(number);

To check:

if (map.get(key).contains(number)) // now safe

The null checking code is no longer necessary.

——

Java 8 update:

To deal with the null entry problem when adding to the set:

map.computeIfAbsent( key, k -> new HashSet<>() ).add(number);

and for null safe checking:

if ( map.getOrDefault(key, Collections.emptySet() ).contains(number))


回答3:

Why not look at this:

https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap

MultiMap allows you to store multiple values for a given key in a very efficient way.

In your case, great advantage is that you are not forced to retrieve a value (Set) from a given key in order to add some values to it.

Indeed, you just have to add the value to the key as if you deal with "monovalue" and it will be automatically added to the set in background.



回答4:

Map<String,Set<Integer>> map;  
Set<Integer> set = map.get("apple");  

I omit the actual population of the map since the OP is how to get the set i.e. the value



回答5:

Map<String, Set<Integer>> mapOfSets = new HashMap<String, Set<Integer>>();
Set<Integer> numberSet = new HashSet<Integer>();

//put a set into the map
mapOfSets.put("key", numberSet);
//get a set out of the map
Set<Integer> set = mapOfSets.get("key");


回答6:

If you want to add multiple numbers to a set with one method, try this:

Map<String, Set<Integer>> map; // Definition


public void addValues(String key, Integer... values) {
    map.get(key).addAll(values);
}

This way, when you need to add a bunch of numbers for a key you can make a call like this:

addValues("apple", 1, 2, 4, 6, 8);

One line instead of 5.



回答7:

this is just an example full class. just run it and work on it to understand more about this issue

public class Tester5 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        //"apple", "orange", "grape", etc. Each set will contain random numbers: 1, 2, 3, 4, 5, 6, 7, 8, 9

        Random ran = new Random();

        Map<String, Set<Integer>> map= new HashMap<String, Set<Integer>>();
        String keys[]= {"apple", "orange", "grape"};
        for(String key : keys) {
            Set<Integer> integers= new HashSet<Integer>();
            for(int i = 0; i < 10; i++) {
                 integers.add(ran.nextInt(9)+1);
            }
            map.put(key, integers);
        }
        System.out.println(map.toString());

    }

}