Java 8 streams - collect and stream map of lists

12,800

Solution 1

It looks like all you need is flatMap the values of the original Map and then continue processing as you currently do:

Collection< PublicationSession > wantedPublications = 
    effectiveDatePublicationMap.values() // Collection<List<PublicationSession>>
                               .stream() // Stream<List<PublicationSession>>
                               .flatMap(list->list.stream()) // Stream<PublicationSession>
                               .filter(pub -> PublicationStatus.valueOf(pub.getPublishStatus()) == PublicationStatus.COMPLETE)
                               .sorted(Comparator.comparing(PublicationSession::getCreateTime))
                               .collect(toMap(p -> p.getPublicationSession().getEffDateTime(), UnaryOperator.identity(), PICK_LATEST))
                               .values();

Solution 2

To obtain the same result of your iterative code

List< PublicationSession> publicationsToFilter = new ArrayList<>();
for (List< PublicationSession> sessions : effectiveDatePublicationMap.values()) {
    publicationsToFilter.addAll(sessions);
}

with streams you first have to use flatMap to transoform your stream of List<PublicationSession> in a stream of PublicationSession, and then collect all of them in a list with collect(Collectors.toList())

List<PublicationSession> publicationsToFilter = effectiveDatePublicationMap.values()
                                                   .flatMap(Collection::stream)
                                                   .collect(Collectors.toList());

Before collecting the result, you can filter or sort as you wish.

Share:
12,800
Admin
Author by

Admin

Updated on June 14, 2022

Comments

  • Admin
    Admin almost 2 years

    I have a Map of Lists, and would like to collect all the values and then stream on the collected List, so given:-

    Map<LocalDateTime, List<PublicationSession>> effectiveDatePublicationMap;
    

    Below works / shows what I want to do with iteration but I want to do this all in streams, rather than creating an intermediate list using iteration:-

    List< PublicationSession> publicationsToFilter = new ArrayList<>();
    for (List< PublicationSession> sessions : effectiveDatePublicationMap.values()) {
        publicationsToFilter.addAll(sessions);
    }
    
    Collection< PublicationSession > wantedPublications = publicationsToFilter.stream()
                .filter(pub -> PublicationStatus.valueOf(pub.getPublishStatus()) == PublicationStatus.COMPLETE)
                .sorted(Comparator.comparing(PublicationSession::getCreateTime))
                .collect(toMap(p -> p.getPublicationSession().getEffDateTime(), UnaryOperator.identity(), PICK_LATEST))
                .values();
    

    So I wanted to stream the map of lists all into one lists, then work on that sublist in one stream rather than having to do the above in two statements (ie build up the list by iteration, then do the streaming to filter / sort and collect.

    I have so far failed to do so, when I try and stream / collect the map I get compile issues. Could anyone show how to do the above in one step, without having to do iteration then streaming?