Modify local list in parallel stream java

511 Views Asked by At

I have a method like below:

  public void method ()
  {
        List<String> list1 = someOperation();
        List<List2Class> list2;
        long failedCount = 0;
        for (String element : list1) {
            try {
                list2 = someclass.method1(element);
                list2 = someclass.method2(element);
                someclass.saveToDB(list2);
            
            } catch (Exception e) {
                failedCount++;
              
            }
        }
       //some checks on failedCount
    }

I want to convert the for loop into parallel stream, can someone tell me what should be the code changes in the above method for the same? PS - method1 and method2 are returning modified version of list2.

1

There are 1 best solutions below

0
Andy Turner On

The logic here is basically "the result of the last successful operation".

Assuming you don't need the failedCount (you don't show it being used), you can do that like this: map successful operations to a present Optional, failed operations to an absent Optional; and just take the last present optional:

Optional<List<List2Class>> opt = list1.stream()
    .flatMap(element -> Stream.of(runOperation(someclass::method1, element), runOperation(someclass::method2, element))
    .reduce((a, b) -> !b.isPresent() ? a : b);

where runOperation is something like:

Optional<List<List2Class>> runOperation(Function<String, List<List2Class>> operation, String parameter) {
  try {
    return Optional.of(operation.apply(parameter));
  } catch (Exception e) {
    return Optional.absent();
  }
}

You then need to decide what value list2 should have if no operations succeed.

If you actually do need the failedCount, you can break this up a bit:

Stream<Optional<List<List2Class>>> intermediate =
    list1.stream()
        .flatMap(element -> Stream.of(runOperation(someclass::method1, element), runOperation(someclass::method2, element));

Map<Boolean, List<Optional<List<List2Class>>>> partitioned =
    intermediate.collect(Collectors.partitioningBy(Optional::isPresent));

Now partitioned.get(true) has all the successful results, while partitioned.get(false) has all the failed results. So:

Optional<List<List2Class>> opt = partitioned.get(true).stream().reduce((a, b) -> !b.isPresent() ? a : b);
long failedCount = partitioned.get(false).size();