1

I have Following use case:

    User Object is as followed:
    UserId      payload
    123         abc1
    123         abc2
    456         pqr1
    456         pqr2
    678         xyz1

And after iterating above list<User Object>, Result should be like: 
{123=[abc1, abc2], 456=[pqr1,pqr2], 678=[xyz1]}

so that I can use value(list of other objects) for key(123) for further processing. What will be best way to do it?

I have tried below but not sure how performance efficient if object size increases.

Map<String,List<String>> userMap = new HashMap<String, List<String>>();     
for(User user: users) {
  String userId = user.getUserId();
  List<String> payloads = new ArrayList<String>();
  if(userMap.containsKey(userId)) {
      payload = userMap.get(userId);
                  payloads.add(user.getPayload());
      userMap.put(userId, payloads);
  }
  else {
      payloads.add(user.getPayload());
      userMap.put(user.getUserId(), payloads);
  }
 }
yateen
  • 85
  • 1
  • 7
  • You should only create a new ArrayList if you need one. And you should not put the list if it's already in the map. And you can just call get() and check if the value is null instead of using containsKey. But unless you have millions of users, you probably won't notice any difference. – JB Nizet Aug 13 '19 at 18:47
  • You could also use Streams and their groupingBy collector to make the code simpler. Which what you should aim for, rather than performance. – JB Nizet Aug 13 '19 at 18:48

2 Answers2

5

The easiest way would be to stream the List and use Collectors#groupingBy and Collectors#mapping:

Map<String, List<String>> userMap = users.stream()
    .collect(Collectors.groupingBy(User::getUserId, 
        Collectors.mapping(User::getPayload, Collectors.toList())));

Output:

{123=[abc1, abc2], 456=[pqr1, pqr2], 678=[xyz1]}
Jacob G.
  • 28,856
  • 5
  • 62
  • 116
0

Another possible solution would be to use Guavas Maps.toMap

twobiers
  • 1,057
  • 1
  • 11
  • 27