Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a custom type instead of Integer when using Collectors.summingInt?

I am currently creating a Map<String, Map<LocalDate, Integer>> like this, where the Integer represents seconds:

Map<String, Map<LocalDate, Integer>> map = stream.collect(Collectors.groupingBy(
            x -> x.getProject(),
            Collectors.groupingBy(
                x -> x.getDate(),
                Collectors.summingInt(t -> t.getDuration().toSecondOfDay())
            )
        ));

How could I instead create a Map<String, Map<LocalDate, Duration>>?

like image 778
Alex78191 Avatar asked May 31 '17 13:05

Alex78191


2 Answers

To change that Integer from Collectors.summingInt to a Duration, you simply need to replace that Collector with:

Collectors.collectingAndThen(
    Collectors.summingInt(t -> t.getDuration().toSecondOfDay()),
    Duration::ofSeconds
)
like image 183
Eugene Avatar answered Oct 07 '22 12:10

Eugene


If you were using an actual Duration for getDuration() (instead of LocalTime), you could also sum directly the Duration's as follows:

Map<String, Map<LocalDate, Duration>> map = stream.collect(Collectors.groupingBy(
        MyObject::getProject,
        Collectors.groupingBy(
                MyObject::getDate,
                Collectors.mapping(MyObject::getDuration,
                        Collectors.reducing(Duration.ZERO, Duration::plus))
        )
));

With the advantage that it also sums the nanoseconds, and could be generalized to other types as well.

Note however that it creates many intermediate Duration instances which could have an impact on the performance.

like image 40
Didier L Avatar answered Oct 07 '22 11:10

Didier L