Modify local list in parallel stream java

503 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
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();