Use the simple groupingBy variant:
Map<String, List<Pojo>> map = pojos
.stream()
.collect(
Collectors.groupingBy(Pojo::getKey)
);
Answer from Eran on Stack OverflowUse the simple groupingBy variant:
Map<String, List<Pojo>> map = pojos
.stream()
.collect(
Collectors.groupingBy(Pojo::getKey)
);
Also, if you wanted to return a similar map but instead of whole Pojo you wanted the map's values be some property of the Pojo, you would do like that:
Map<String, List<String>> map = pojos
.stream()
.collect(
Collectors.groupingBy(
Employee::getKey,
Collectors.mapping(
Pojo::getSomeStringProperty,
Collectors.toList()
)
)
);
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);
});
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.
You need to chain a Collectors.mapping() collector to the Collectors.groupingBy() collector:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity,
Collectors.mapping(d->createFizz(d),Collectors.toList())));
If createFizz(d) would return a List<Fizz, you can flatten it using Java 9's Collectors.flatMapping:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity,
Collectors.flatMapping(d->createFizz(d).stream(),Collectors.toList())));
If you can't use Java 9, perhaps using Collectors.toMap will help:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.toMap(DistrictDocument::getCity,
d->createFizz(d),
(l1,l2)->{l1.addAll(l2);return l1;}));
In case you'd like to do a doubly nested grouping:
Let's say you have a collection of EducationData objects that contain School name, teacher name, and student name. But you want a nested map that looks like :
What you have
class EducationData {
String school;
String teacher;
String student;
// getters setters ...
}
What you want
Map<String, Map<String, List<String>>> desiredMapOfMpas ...
// which would look like this :
"East High School" : {
"Ms. Jackson" : ["Derek Shepherd", "Meredith Grey", ...],
"Mr. Teresa" : ["Eleanor Shellstrop", "Jason Mendoza", ...],
....
}
How to Get There
import static java.util.stream.Collectors.*;
public doubleNestedGroup(List<EducationData> educations) {
Map<String, Map<String, List<String>>> nestedMap = educations.stream()
.collect(
groupingBy(
EducationData::getSchool,
groupingBy(
EducationData::getTeacher,
mapping(
EducationData::getStudent,
toList()
)
)
)
);
}
before
.stream()
.collect(Collectors.toMap((m) -> m.get("date"), m -> m, (a,b) -> {
Map<String, String> res = new HashMap<>();
res.putAll(a);
res.putAll(b);
return res;
}))
.values();
This is the solution you're looking for.
The toMap function receives 3 parameters:
- the key mapper, which in your case is the date
- the value mapper, which is the map itself that's being processed
- the merge function, which takes 2 maps with the same date and puts all the keys together
Output:
[{date=2020.1.5, A=20, B=10}, {date=2020.1.6, A=30}, {date=2020.1.7, C=30}]
You can do this way using groupingBy and Collector.of
List<Map<String, String>> list = new ArrayList<>(before.stream()
.collect(Collectors.groupingBy(
k -> k.get("date"),
Collector.of( HashMap<String,String>::new,
(m,e)-> m.putAll(e),
(map1,map2)->{ map1.putAll(map2); return map1;}
))).values());
Here, first use Collectors.groupingBy to group by date. Then define custom collector using Collector.of to collect List<Map<String, String>> into Map<String, String>. After create list using map values.
And using Collectors.flatMapping from Java 9
List<Map<String, String>> list = new ArrayList<>(before.stream()
.collect(Collectors.groupingBy(
k -> k.get("date"),
Collectors.flatMapping(m -> m.entrySet().stream(),
Collectors.toMap(k -> k.getKey(), v -> v.getValue(), (a,b) -> a))))
.values());