-1

I have the following snippet and I wonder if and how it is possible to replace it with Java-streams/Java 8 API

List<Borrower> borrowers = creditcomplex.getBorrowers();
for (Borrower borrower : borrowers) {
    List<Facility> facilities = borrower.getFaciliies();
    for (Facility facility : facilities) {
        List<RepaymentSchedule> repaymentScheduleList = facility.getrepaymentSchedule();
        if (repaymentScheduleList != null) {
            for (RepaymentSchedule repaymentschedule : repaymentScheduleList) {
                double[] repayment = 
                    amortizationService.calculateAmortizationSchedule(repaymentschedule);
                double[] drawdown = 
                    amortizationService.calculateRepaymentSchedule(repaymentschedule);
                double[] outstandingProfie = amortizationService
                        .calculateOutstandingSchedule(repaymentschedule);
            }
        }
    }
}
Andronicus
  • 25,419
  • 17
  • 47
  • 88
SanthoshT
  • 11
  • 2
  • 2
    I'd probably look to fold some of the above functionality into (say) the Borrower class, the Facility class etc. Then you can ask those classes and delegate, rather than pulling objects out of objects out of objects.... See https://en.wikipedia.org/wiki/Law_of_Demeter for more on this.... You *may* need to pass the amortizationService around, note... – Brian Agnew Feb 06 '20 at 16:07

2 Answers2

4

You can use flatMap:

creditcomplex.getBorrowers().stream()
    .flatMap(b -> b.getFaciliies().stream())
    .flatMap(f -> Optional.ofNullable(f.getrepaymentSchedule()).stream())
    .forEach(repaymentschedule -> {
            double[] repayment = 
                amortizationService.calculateAmortizationSchedule(repaymentschedule);
            double[] drawdown = 
                amortizationService.calculateRepaymentSchedule(repaymentschedule);
            double[] outstandingProfie = amortizationService
                    .calculateOutstandingSchedule(repaymentschedule);
    });

P.S.1: Note that Optional#stream appeared in java 9, you might need to use:

optional.map(Stream::of).orElseGet(Stream::empty)

It's taken from here.

P.S.2: What you're doing in a forEach does not have any effect (you're declaring and initializing arrays inside, but you cannot use them outside of the loop. I left the code because it can be replaced with any computation on the nested elements.

P.S.3: Returning null instead of empty list is error prone and it's usually better to go with an empty list.

Andronicus
  • 25,419
  • 17
  • 47
  • 88
1

Untested, but it should roughly be

List<RepaymentSchedule> repaymentSchedules = creditcomplex.getBorrowers().stream()
    .flatMap(borrower -> borrower.getFacilities().stream())
    .map(facility -> facility.getrepaymentSchedule())
    .filter(repaymentScheduleList -> repaymentScheduleList != null)
    .flatMap(repaymentScheduleList -> repaymentScheduleList.stream())
    .collect(Collectors.toList());

would be one thing, and from here youcan create the arrays.

Alternatively, you can omit the .collect() and instead do

.forEach(repaymentSchedule -> {
    double[] repayment = 
                amortizationService.calculateAmortizationSchedule(repaymentschedule);
    double[] drawdown = 
                amortizationService.calculateRepaymentSchedule(repaymentschedule);
    double[] outstandingProfie = amortizationService
                    .calculateOutstandingSchedule(repaymentschedule);
});
glglgl
  • 89,107
  • 13
  • 149
  • 217