user2761895
user2761895

Reputation: 1541

Create multiple maps from a list in Java 8

Is there a way to create multiple maps from a list in Java 8 using stream or other way?

I have a list of custom object. Suppose List where Employee has departmentId so there are some employees which have the same departmentId = "001" for example. I want to create multiple maps based on Employee.departmentId.

For example,

map1 = <"001", employee1>,<"001", employee3>, <"001", employee8>...<"001", employee100>

map2 = <"002", employee2>,<"002", employee4>,..., <"002", employee8> ... something like this.

since for each element in list check the departmentId and put it in corresponding map by using old for loop. Wondering is there a better way to do this? Currently I'm using Java 8

Upvotes: 4

Views: 3082

Answers (3)

WJS
WJS

Reputation: 40057

As has been suggested, using a Map<String,List<Employee>> is probably what you want. I constructed a small class and an example to illustrate the process.

      List<Employee> emps = List.of(
            new Employee("001", "Jim"),
            new Employee("002", "Bob"),
            new Employee("001", "June"),
            new Employee("002", "Jean"));

     // For each employee, using departmentId as the key, construct
     // a map containing lists of all employees that have that ID

      Map<String, List<Employee>> empMap = 
          emps
              .stream()
              .collect(
                  Collectors.groupingBy(emp -> emp.departmentId)
              );

      for (Entry<?, ?> e : empMap.entrySet()) {
         System.out.println(e.getKey() + "-->" + e.getValue());
      }



      class Employee {
          public String departmentId;
          public String name;
    
          public Employee(String departmentId, String name) {
             this.departmentId = departmentId;
             this.name = name;
          }
          public String toString() {
             return "(" + departmentId + " " + name + ")";
          }
       }

This displays

001-->[(001 Jim), (001 June)]
002-->[(002 Bob), (002 Jean)]

Another option, which would do the exact same thing is as follows:

This creates an empty map. Then it iterates over the list of employees and computes whether the value for the key exists. If it does, it returns the list and adds the entry to that list. If it doesn't, it then creates the new ArrayList and then adds the employee for that list, storing the list in the provided key.

     Map<String, List<Employee>> emp2 = new HashMap<>();
         for (Employee emp : emps) {
            emp2.compute(emp.departmentId,
               (ID, list) -> list == null ? new ArrayList<>()
                     : list).add(emp);
      }

In this case my preference would be the first method.

Upvotes: 3

ZINE Mahmoud
ZINE Mahmoud

Reputation: 1332

none of the existing Java core Map implementations allow a Map to handle multiple values for a single key.

if we try to insert two values for the same key, the second value will be stored, while the first one will be dropped.

Map<String, String> map = new HashMap<>();
assertThat(map.put("key1", "value1")).isEqualTo(null);
assertThat(map.put("key1", "value2")).isEqualTo("value1");
assertThat(map.get("key1")).isEqualTo("value2");

you can achieve what you want by using Collection as Value here is a simple example :

using java version < 8

Map<String, List<String>> map = new HashMap<>();
List<String> list = new ArrayList<>();
map.put("key1", list);
map.get("key1").add("value1");
map.get("key1").add("value2");

assertThat(map.get("key1").get(0)).isEqualTo("value1");
assertThat(map.get("key1").get(1)).isEqualTo("value2");

using java version > 8

Map<String, List<String>> map = new HashMap<>();
map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value1");
map.computeIfAbsent("key1", k -> new ArrayList<>()).add("value2");

assertThat(map.get("key1").get(0)).isEqualTo("value1");
assertThat(map.get("key1").get(1)).isEqualTo("value2");

what you want exactly you can achieve it by using Apache Library !

Solution : add Maven or jar

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-collections4</artifactId>
  <version>4.1</version>
</dependency>

then :

MultiValuedMap<String, Employe> map = new ArrayListValuedHashMap<>();
map.put("key1", new Employe("blahblah"));
map.put("key1", new Employe("blahblah"));
map.put("key1", new Employe("blahblah"));

Other alternatives libraries : Guava Multimap
Link : https://guava.dev/releases/23.0/api/docs/com/google/common/collect/Multimap.html

Upvotes: 0

Dhrumil Patel
Dhrumil Patel

Reputation: 362

It is not possible to do this. Because Map can not have duplicate key. You can create Map<String,List<Employee>> by using Collectors.groupingBy()

Upvotes: 0

Related Questions