Sort List of objects by date and applying filter

Viewed 350

I have list of Payments:

Payment 1
  CountyTaxAmount = 250.00
  CityTaxAmount   = 101.00
  LienAmount      = 0.00
  HazardAmount    = 0.00
  PaymentDueDate  = "2018-06-01"

Payment 2
  CountyTaxAmount = 10.00
  CityTaxAmount = 20.00
  LienAmount      = 0.00
  HazardAmount    = 0.00
  PaymentDueDate = "2018-05-01"

I created a function that takes in this list and currentDueDate. If paymentDueDate is equal to or before currentDueDate and one that's closest to currentDueDate, I want to use that row in my calculations.

For some reason my sort is not working properly. Can someone shed some light on what I am doing wrong. Here is my code:

private EscrowStatusEnum determineEscrowStatus(Payment pcm, LocalDate currentDueDate) {
    EscrowStatusEnum escrowStatus = null;

    if(currentDueDate!= null && pcm!=null 
            && pcm.getPayment() != null 
            && !pcm.getPayment().isEmpty()) {

        Predicate<Payment> pcmRow = 
                it->it.getPaymentDueDate()!=null && !it.getPaymentDueDate().isAfter(currentDueDate);

        final Payment sortedRow = 
                pcm.getPayment().stream().sorted((el1, el2) -> el1.getPaymentDueDate().compareTo(el2.getPaymentDueDate())).
                filter(pcmRow).findFirst().orElse(null);

        if(sortedRow != null) {

            BigDecimal countyCityLienHazardSum = sortedRow.getCountyTaxAmount().add(sortedRow.getCityTaxAmount()).add(sortedRow.getLienAmount()).add(sortedRow.getHazardAmount());
            BigDecimal countyCityLienSum = sortedRow.getCountyTaxAmount().add(sortedRow.getCityTaxAmount()).add(sortedRow.getLienAmount());

            if(countyCityLienHazardSum.compareTo(BigDecimal.ZERO) == 0)
                escrowStatus = EscrowStatusEnum.NONESCROWED;
            else if(countyCityLienSum.compareTo(BigDecimal.ZERO) > 0 && sortedRow.getHazardAmount().compareTo(BigDecimal.ZERO) == 0 ||
                    countyCityLienSum.compareTo(BigDecimal.ZERO) >= 0 && sortedRow.getHazardAmount().compareTo(BigDecimal.ZERO) > 0)
                escrowStatus = EscrowStatusEnum.ESCROWED;
        }
    }

    return escrowStatus;
}

When I pass in currentDueDate of "2018-06-01", I want my code to return Payment 1.

Currently it is returning Payment 2.

If I remove Payment 2 from my tests, then it returns Payment 1.

So something must be wrong with sort.

2 Answers

Your sort returns the earliest date. What you want is the latest date that is earlier than the cutoff.

To find the smallest or largest value in a stream, don't use sort(...).findFirst(). Use max or min instead. In your case:

sortedRow = pcm.getPayment().stream()
               .filter(pcmRow)
               .max(Comparator.comparing(Payment::getPaymentDueDate))
               .orElse(null);   // not relevant to your question but consider not using nulls so much

The problem is in the filter:

!it.getPaymentDueDate().isAfter(currentDueDate)

This allows the payment due date to be the same as the current due date, but you only want overdue payments.

Change it to this:

it.getPaymentDueDate().isBefore(currentDueDate)
Related