1

I have a java method that returns below output:

List<CompletableFuture<List<String>>> futureResponselist;

How can I construct a single list from this data? As I have to iterate the final output and do some operation with the "string" param that is present inside.

I want all the string values present inside these lists in a final single list.

It should be as: List<String> My futureResponselist size is 3.so the conversion TO List should happen in nonblocking way

Debo
  • 41
  • 8
  • Are you going to use only string values? – fatih Jul 04 '21 at 05:53
  • i need the out put as List Fatih --@Fatih. Basically every data inside the list is as string accountId+":"+status;Ya..i want only the string values @Fatih – Debo Jul 04 '21 at 05:56

4 Answers4

3

You have many ways to do this. To flatten nested lists for Java 8 and higher, you can use a structure like below to do it functionally. If you want to process in parallel you can use Collection::parallelStream instead of Collection::stream.

List<String> onlyStringValues = futureResponseList.stream()
                                            .map(CompletableFuture::join)
                                            .flatMap(Collection::stream)
                                            .collect(Collectors.toList());
fatih
  • 1,285
  • 11
  • 27
  • @Faith -it will be non blacking correct?So, my batch size is 3 and i have called supplyAsync method thrice.so,the futureResponseList size is 3.I dont want the main thread should get blocked till the 1st batch is completed .It will be doing in non blocking way correct? – Debo Jul 04 '21 at 06:34
  • @hatefAlipoor Thanks, I didn't know that. I edited my answer in a different way. – fatih Jul 04 '21 at 07:03
  • @Debo Looking through the answer [here](https://stackoverflow.com/questions/58376577/why-main-thread-is-not-waiting-for-other-async-processthreads-to-complete-all) may be helpful to you. – fatih Jul 04 '21 at 07:17
1

It's actually quite simple: Iterate the outer list using an enhanced for loop, get the inner list from the CompletableFuture and add all the elements to the result list.

List<CompletableFuture<List<String>>> futureResponselist = ...

List<String> result = new ArrayList<>();
for (CompletableFuture<List<String>> future : futureResponselist)
    result.addAll(future.get());
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • 1
    Hi Andress,future.get() is blocking call correct..I dont want it to get blocked.my futureResponselist is 3.so the conversion should happen in non blocking way – Debo Jul 04 '21 at 06:35
  • @Debo Question says you want **all** the values, so you *have* to block to wait for them to be available. Of course, if you don't want to block, simply add `if (future.isDone())`, so it skips future that aren't ready yet. That should be so obvious that I'm baffled why you didn't figure that out yourself, unless of course you haven't even looked at the javadoc of `CompletableFuture` is see what it supports. Please do that now, so you don't ask questions you already have readily available answers to with a click of a button. – Andreas Jul 04 '21 at 08:15
1

you can use this code, if the order of list is not important consider parallelizsing it

List<CompletableFuture<List<String>>> futureResponselist = new ArrayList<>();
futureResponselist.add(CompletableFuture.supplyAsync(() -> List.of("1" , "2")));
futureResponselist.add(CompletableFuture.supplyAsync(() -> List.of("3" , "4", "5")));
futureResponselist.add(CompletableFuture.supplyAsync(() -> List.of("6")));
List<String> result = futureResponselist
        .stream()
        .map(CompletableFuture::join)
        .flatMap(List::stream)
        .collect(Collectors.toList());

update: more general approach it is adopted from the Modern Java in Action

Executor executor =
        Executors.newFixedThreadPool(5);
List<CompletableFuture<List<String>>> futureResponselist = new ArrayList<>();
futureResponselist.add(CompletableFuture.supplyAsync(() -> List.of("1" , "2"), executor));
futureResponselist.add(CompletableFuture.supplyAsync(() -> List.of("3" , "4", "5"), executor));
futureResponselist.add(CompletableFuture.supplyAsync(() -> List.of("6"), executor));

List<CompletableFuture<List<String>>> futureResult = futureResponselist
        .stream()
        .map(future -> future.thenApply(Function.identity())) // do some processing with list here we just return it but you can do something else
        .map(future -> future.thenApply(Function.identity()))
        .collect(Collectors.toList());
futureResult
                    .parallelStream()
                    .map(CompletableFuture::join)
                    .flatMap(List::stream)
                    .forEach(System.out::println); // do something when the result is ready here we just print it
badger
  • 2,908
  • 1
  • 13
  • 32
  • 1
    Almost there, but question specifies that the result should be a `List`, not the printing of the elements. – Andreas Jul 04 '21 at 06:18
  • my futureResponselist is 3.so the conversion should happen in non blocking way..@hatef ..my requirement is ..after get thsi LIst,i have iterate this final list and with every element present i have post it to do some operation.. – Debo Jul 04 '21 at 06:37
  • hI @hatef, yes i have done in parallel way ..so my batch size was 3.so supplyasyn was called thrice and every call returned one CompletableFuture>> ..so size of futureResponselist is 3 – Debo Jul 04 '21 at 06:40
  • @Debo I update the answer, hope it helps you – badger Jul 04 '21 at 07:05
0

Iterate futureResponselist and then iterate list of String for each CompletableFuture and add the string to list declared outside of both for loop

List<CompletableFuture<List<String>>> futureResponselist;

// List of string to store combined result
List<String> mergedList = new ArrayList<>();

for (CompletableFuture com : futureResponselist) {
    for (String string : com.getYourListOfString()) {
        mergedList.add();
    }
}
sanjeevRm
  • 1,541
  • 2
  • 13
  • 24
  • really sorry to ask again as i have started new in java:here com.getYourListOfString()) what to pass? not getting the syntex.how to pur each on CompletableFuture object.How will is get the list of string from CompletableFuture object – Debo Jul 04 '21 at 06:08
  • Thanks a lot @hatef Alipoor :-)it helped a lot.My problem looks to be solved – Debo Jul 04 '21 at 12:17