简体   繁体   中英

How to use Java streams to combine child generated lists into a single list?

In my code below, I don't like that I have the List<EmailDraft> list defined outside of the stream. I'm pretty sure there is a way to have the stream processing return a List<EmailDraft> list directly, I'm just not sure how to do this. Thoughts?

List<EmailDraft> drafts   /* <-- don't like this */
    = new LinkedList<>();

List<SyndFeed> feeds
    = evnt.getFeeds();

feeds.stream().forEach(
    sf -> sf.getEntries().stream().forEach(se -> {

        EmailDraft ed = new EmailDraft();

        // Title
        ed.setTitle(sf.getTitle());

        // ....     

        // Add to list
        drafts.add(ed);  /* <-- don't like this either */
    })
);

You can use flatMap on the feeds and collect all the EmailDrafts in a list as following:

List<EmailDraft> emailDrafts =
            feeds.stream()
                 .flatMap(
                         sf -> sf.getEntries().stream().map(se -> {

                             EmailDraft ed = new EmailDraft();

                             // Title
                             ed.setTitle(sf.getTitle());

                             return ed;
                         })
                 ).collect(Collectors.toList());

Use map

feeds.stream().flatmap(
    sf -> sf.getEntries().stream()).map(se -> {

        EmailDraft ed = new EmailDraft();

        // Title
        ed.setTitle(sf.getTitle());

        // ....     

        return ed;
    })
);

Another alternative using range to create stream of title repeated for the number of elements in sf.getEntries() :

        List<EmailDraft> drafts = feeds.stream()
        .flatMap( sf -> IntStream.range( 0, sf.getEntries().size() ).mapToObj( i -> sf.getTitle() ) )
        .map( t -> { 
                       EmailDraft ed = new EmailDraft(); 
                       ed.setTitle(t); 
                       return ed;
                    } 
        )
        .collect( Collectors.toList() );

Instead of overcomplicating things and doing everything with streams, you just could do it the old pre Java-8 way:

List<EmailDraft> drafts = new ArrayList<>();
for(SyndFeed sf : feeds){
    for(int i = sf.getEntries().size(); i > 0; i--){
        EmailDraft ed = new EmailDraft();
        ed.setTitle(sf.getTitle());
        drafts.add(ed);
    }
}

which IMO should be preferred because it is such a simple task.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM