Converting Stream<Stream<T>> to List<T>

Viewed 776

I am new to java 8. I have written following piece of code:

Stream<Stream<POLine>> list = poSearchResponseList.stream().map(poSearchResponse ->
        poSearchResponse.getDeliveryDocumentLines().stream().map(deliveryDocumentLine ->
                POLine.builder()
                        .poLineNumber(deliveryDocumentLine.getPurchaseReferenceLineNumber())
                        .quantity(deliveryDocumentLine.getExpectedQty())
                        .vnpkQty(deliveryDocumentLine.getVnpkQty())
                        .build()));

I want to get

List<POList>

from this right hand expression. Cannot understand how to convert this Stream of stream to a list.

3 Answers

Using flatMap, it's trivial to convert a Stream<Stream<POLine>> to a Stream<POLine>:

List<POLine> output = 
    list.flatMap(Function.identity())
        .collect(Collectors.toList());

Though it might be simpler to produce a List<POLine> directly:

List<POLine> list = 
    poSearchResponseList.stream()
                        .flatMap(posr -> posr.getDeliveryDocumentLines()
                                             .stream()
                                             .map(dl -> 
                                                 POLine.builder()
                                                       .poLineNumber(dl.getPurchaseReferenceLineNumber())
                                                       .quantity(deliveryDocumentLine.getExpectedQty())
                                                       .vnpkQty(deliveryDocumentLine.getVnpkQty())
                                                       .build()))
                        .collect(Collectors.toList());

Why do you want to get a Stream<Stream<POLine>> list?? You already have a list of POLine from the poSearchResponseList instance.

So, I think you have a List<SearchResponse> which has a List<DeliveryDocumentLine> and from this you want to get a List<POList>, right?

If that is the scenario you can use Stream.flatMap() method.

Why?

Well, it is because this method can produce something like this Stream<SearchResponse> -> Stream<POList>

Now, first you extract SearchResponse using .stream() then you flat it using Stream.flatMap() then here you will have a SearchResponse object from this object you can extract the data of the lines, like this:

List<POLine> list = poSearchResponseList
        .stream()
        .flatMap(response -> response.getDeliveryDocumentLines()
                .stream()
                .map(item -> POLine.builder()
                        .poLineNumber(item.getPurchaseReferenceLineNumber())
                        .quantity(item.getExpectedQty())
                        .vnpkQty(item.getVnpkQty())
                        .build()
                )
        )
        .collect(Collectors.toList());
System.out.println(list);

To see it in separate steps for better readability we can write it accordingly:

        List<POLine> list =
                poSearchResponseList.stream()
                        .map(POLine::getDeliveryDocumentLines)
                        .flatMap(Stream::of)
                        .map(dl ->
                                POLine.builder()
                                        .poLineNumber(dl.getPurchaseReferenceLineNumber())
                                        .quantity(deliveryDocumentLine.getExpectedQty())
                                        .vnpkQty(deliveryDocumentLine.getVnpkQty())
                                        .build())
                        .collect(Collectors.toList());

What it does:

  • Creates stream from poSearchResponseList,
  • then mapps elements to deliveryDocumentLines, returning: Stream<List<DeliveryDocumentLine>>
  • reducing List with to stream method to type Stream<DeliveryDocumentLine>
  • in last step mapping to expected type and collecting to expected collection.
Related