Reputation: 129
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??
Upvotes: 2
Views: 6116
Reputation: 120858
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);
});
Upvotes: 7
Reputation: 140318
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.
Upvotes: 0
Reputation: 45319
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.
Upvotes: 3