Add to List Value on HashMap

I fill out a hashmap so that my objects are grouped by one of their attributes. I find it "ugly" to check if a list (value) exists before adding my object to it.

An example will be more explicit:

// Need a map to group Person by age. // Person = {age: int} Map<Integer, List<Person>> myHashMap = new HashMap(); for (Person person : persons) { int age = person.getAge(); List<Person> personsOfSameAge = myHashMap.get(age); if (personsOfSameAge != null) { personsOfSameAge.add(person); } else { personsOfSameAge = new ArrayList(); personsOfSameAge.add(person); myHashMap.put(age, personsOfSameAge); } } 

Is there a better way to code this?

 myHashMap.addToValueListOrCreateValueList(myObject); 
+7
java hashmap null-check
source share
4 answers

In Java 8, all of your code can be written like this (like other great answers):

 Map<Integer, List<Person>> myHashMap = new HashMap(); for (Person person : persons) { myHashMap.computeIfAbsent(age,age->new ArrayList<Person>()).add(person); } 

But you can be even shorter using a stream that collects in a Map with Collectors.groupingBy() :

 Map<Integer, List<Person>> myMap = persons.stream().collect(Collectors.groupingBy(Person:getAge)); 

As a side note, your actual Java 7 code can also be improved. Of course, not as much as with Java 8, but if you cannot use Java 8, this can be interesting.
In your actual code, this is duplicated:

 personsOfSameAge.add(person); 

And you use two conditional statements ( if and else ), while only if will be enough if you first handle the special case: there is no value in Map . Here is a modified version:

 Map<Integer, List<Person>> myHashMap = new HashMap<>(); for (Person person : persons) { int age = person.getAge(); List<Person> personsOfSameAge = myHashMap.get(age); if (personsOfSameAge == null) { personsOfSameAge = new ArrayList(); myHashMap.put(age, personsOfSameAge); } personsOfSameAge.add(person); } 
+7
source share

Yes, there is in Java 8:

 List<Person> personsOfSameAge = myHashMap.computeIfAbsent(age,age->new ArrayList<Person>()); personsOfSameAge.add(person); 

Or simply

 myHashMap.computeIfAbsent(age,age->new ArrayList<Person>()).add(person); 
+7
source share

Something like that?

  List<Person> newList = Optional.ofNullable( myHashMap.get(age)).orElse(new ArrayList<>()); newList.add(person); myHashMap.put(age, newList); 
+1
source share

Although the question involves doing this in Java 8, I am posting this as an alternative way.

You can use MultiMap from Google Guava .

 Multimap<String, Person> myHashMap = ArrayListMultimap.create(); for (Person person : persons) { myHashMap.put(person.getAge(), person); } 

However, you should know the difference: the Java map returns null for a nonexistent key, and an empty List returned in Google Guava MultiMap.

From javadoc to get (key) MultiMap

Returns a collection of representations of the values ​​associated with the key in this multimag, if any. Note that when containsKey (key) is false, it returns an empty collection, not null. Changes to the returned collection will update the underlying multimap and vice versa

+1
source share

All Articles