2

I have a

List<Map<String, Object>>

coming from a Spring NamedParameterJdbcTemplate queryForList call. The data return looks like this:

[{"id":5,"uid":6}, {"id":5,"uid":7}, {"id":6,"uid":8}, {"id":7,"uid":7}, {"id":8,"uid":7}, {"id":8,"uid":9}]

How can I rearrange the data in the following format?

{5:[6, 7], 6:[8], 7:[7], 8:[7, 9]}

Im looking to return a Map<Integer, List<Integer>>

Anyone have an idea how I can achieve this? Any help much appreciated??

1
  • Look into Collections.groupBy in Java 8 Commented Aug 22, 2018 at 21:13

3 Answers 3

7

This is a job for Collectors.groupingBy with a downstream collector like Collectors.mapping

 Map<Integer, List<Integer>> result = l.stream()
            .collect(Collectors.groupingBy(
                    m -> (Integer) (m.get("id")),
                    Collectors.mapping(m -> (Integer) m.get("uuid"), Collectors.toList())));

Or without streams at all:

list.forEach(x -> {
        Integer key = (Integer) x.get("id");
        Integer value = (Integer) x.get("uuid");
        result.computeIfAbsent(key, ignoreMe -> new ArrayList<>()).add(value);
    });
Sign up to request clarification or add additional context in comments.

1 Comment

I've accepted ernest's answer first because he answered me first. But thanks anyways for your help
3

You can map keys and values to integers while using a grouping-by collector:

List<Map<String, Object>> maps = null;

Map<Integer, List<Integer>> result = maps.stream()
        .collect(Collectors.groupingBy(
                map -> ((Number) map.get("id")).intValue(),
                    Collectors.mapping(map -> ((Number) map.get("uid")).intValue(), 
                            Collectors.toList())));

Using ((Number) map.get("id")).intValue() just in case the value is a Long.

Comments

0

I am not a huge fan of the syntax of the streams API: I think it might be easier to do using a plain old loop (with a few other Java 8-isms):

Map<Integer, List<Integer>> result = new HashMap<>();
for (Map<String, Object> entry : list) {
  int id = (Integer) entry.get("id");
  int uid = (Integer) entry.get("uid");
  result.computeIfAbsent(id, k -> new ArrayList<>())
      .add(uid);
}

YMMV, of course; I just think this is more pleasant than all of the faffing around with collectors and downstream collectors, and the non-obvious error messages when you make type errors.

2 Comments

@Eugene that is too much to put in a lambda body.
probably a matter of choice, I see no problem with that, unlike python lambdas

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.