Using streams to find a minimum of a list of Date objects from a Map<String, List<Date>>

Viewed 491

What I tried initially

Map<String, List<Date>> subscriberCreatedDateSet = data.stream().collect(Collectors
            .groupingBy(SubscriberActivityAggData::getSubscriberAddress
                    , Collectors.mapping(SubscriberActivityAggData::getEventTime, Collectors.toList())));

and then

Map<String, Date> subscriberCreatedDate =  subscriberCreatedDateSet.entrySet().stream()
                .map(item->Collections.min(item.getValue()))
                .collect(Collectors.mapping());

this is incomplete because I could not find a way to correctly do it.

is there a way to do it properly? or should I loops and o it
2 Answers

You can do it in a single pipeline:

Map<String, Optional<Date>> subscriberCreatedDate = 
    data.stream()
        .collect(Collectors.groupingBy(SubscriberActivityAggData::getSubscriberAddress,
     Collectors.mapping(SubscriberActivityAggData::getEventTime,
                        Collectors.minBy(Date::compareTo))));

The only downside is that you get a Map<String, Optional<Date>> instead of Map<String, Date>, but since none of the groups can be empty, the Optional can't be empty either, so you'll just have to add .get() each time you access that Map.

For example:

Date someDate = subscriberCreatedDate.get("someKey").get();

Or, you can run a second Stream pipeline on the entries of that Map to produce a Map<String,Date>.

You can simply do that in single pipeline using toMap instead of groupingBy as:

Map<String, Date> subscriberCreatedDate = data.stream()
        .collect(Collectors.toMap(SubscriberActivityAggData::getSubscriberAddress,
                SubscriberActivityAggData::getEventTime, 
                BinaryOperator.minBy(Comparator.naturalOrder())));

Note - This saves you from the overhead of Optional wrapped values in the resultant Map as well.

Related