Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Map of Map without side-effects using Java 8 Stream

How do I put/add eServiceReportsMapByBatchFile with key oldReportId to eServiceReportMap without side-effects?

Map<String, Map<String, Set<EServiceReport>>> eServiceReportMap = new HashMap<>();
reports.forEach(report -> {
    String oldReportId = report.getOldId();
        Map<String, Set<EServiceReport>> eServiceReportsMapByBatchFile = // processing of batch files
        ...
    eServiceReportMap.put(oldReportId, eServiceReportsMapByBatchFile);
});

return eServiceReportMap;

That is, I want it to become like this:

return reports.stream()
    .map(report -> {
        String oldReportId = report.getOldId();
        Map<String, Set<EServiceReport>> eServiceReportsMapByBatchFile = // processing of batch files
        ...
        // I don't know how and what to return here
    }).collect(// I don't know what to do here);

Thank you.

like image 882
Julez Avatar asked Jan 26 '23 18:01

Julez


2 Answers

You're looking forward mostly to Collectors.toMap which can be used as :

return reports.stream()
        .collect(Collectors.toMap(report -> report.getOldId(),
                        report -> {
                    // batch processing for eServiceReportsMapByBatchFile
                            return eServiceReportsMapByBatchFile;
                }));
like image 191
Naman Avatar answered Jan 31 '23 18:01

Naman


since you call stream on reports, I assume it is a collection of some kind; in such case there is nothing wrong with your side-effects. Notice that someCollection.stream().forEach and someCollection.forEach are very different things, you are more than OK to have side-effects with SomeCollection::forEach - which is nothing but a plain old loop internally.

You could transform that that to a stream solution, but it's going to be a lot less readable:

reports.stream()
       .map(r -> {
            String oldReportId = report.getOldId();
            Map<String, Set<EServiceReport>> eServiceReportsMapByBatchFile =....  
            return new SimpleEntry<>(oldReportId, eServiceReportsMapByBatchFile);
       })
       .collect(Collectors.toMap(
            Entry::getKey,
            Entry::getValue,
            (left, right) -> right; // to match whatever you had until now
       ))
like image 21
Eugene Avatar answered Jan 31 '23 19:01

Eugene