I’m writing a verify function for data normalize between collection in MongoDb I have an object: as below:
class ReleaseTime{
private Date startDate;
private Date endDate;
private List<String> regions;
}
I have to gather all ReleaseTime object that has same startDate
, and same endDate
then merge the Regions list together
I have tried the code below but it just group by startDate
expectedAvailabilities = ungrouppedReleaseTime.stream()
.collect(Collectors.toMap(ReleaseTime::getStartDate,
Function.identity(),
(ReleaseTime tb1, ReleaseTime tb2) ->
{
tb1.getRegions().addAll(tb2.getRegions());
tb2.getRegions().clear();
return tb1;
})
).values();
Thanks for your help!
Here's an alternative way of doing what you want without using streams:
Map<List<Date>, List<String>> map = new LinkedHashMap<>();
ungrouppedAvailabilites.forEach(a ->
map.computeIfAbsent(Arrays.asList(a.getStartDate(), a.getEndDate()), // or List.of
k -> new ArrayList<>())
.addAll(a.getRegions()));
This uses Map.computeIfAbsent
to group regions of ReleaseTime
objects by start and end dates.
In case there are repeated regions among the grouped ReleaseTime
objects and you don't want duplicates, you could use a Set
instead of a List
:
Map<List<Date>, Set<String>> map = new LinkedHashMap<>();
ungrouppedAvailabilites.forEach(a ->
map.computeIfAbsent(Arrays.asList(a.getStartDate(), a.getEndDate()), // or List.of
k -> new LinkedHashSet<>())
.addAll(a.getRegions()));
Note that I'm using LinkedHashMap
and LinkedHashSet
to keep elements in insertion order.
EDIT:
If you need ReleaseTime
objects instead of only their regions, you could achieve it with one extra step:
Map<List<Date>, ReleaseTime> result = new LinkedHashMap<>();
map.forEach((k, v) ->
result.put(k, new ReleaseTime(k.get(0), k.get(1), new ArrayList<>(v))));
This assumes there's a constructor for ReleaseTime
that receives all the attributes:
public ReleaseTime(Date startDate, Date endDate, List<String> regions) {
this.startDate = startDate;
this.endDate = endDate;
this.regions = regions;
}