Sahil
Sahil

Reputation: 245

Get the nearest date to specific from the list of dates?

I have two date fields in Temp class say validFromDate and asOfDate. I have List with me. I need to set the flag whihc is one of the class attributes to true for the record whose validFromDate is closest to asOfDate

Ex.

List<temp> {
    Temp1:
        asOfDate: 2018-01-04
        validFrom: 2018-01-01
    Temp2:
        asOfDate: 2018-01-04
        validFrom: 2018-01-02
    Temp3:
        asOfDate: 2018-01-04
        validFrom: 2018-01-03
}

o/p should be Temp3 as this validFrom is nearest to asOfdate. I will set the flag to true for this Temp2

How can I achieve this using Java 8 streams?

Upvotes: 3

Views: 5202

Answers (3)

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521279

We can try sorting your list based on the absolute difference between the asOfDate and the validFrom date, then take the first element from the sorted list. Something like this:

list.sort((Temp t1, Temp t2)
    ->Long.compare(Math.abs(t1.getAsOfDate().getTime() - t1.getValidFrom().getTime()),
        Math.abs(t2.getAsOfDate().getTime() - t2.getValidFrom().getTime())));
System.out.println(list.get(0));

This assumes that your dates are the old school pre Java 8 java.util.Date class. If not, my code would have to change. This also assumes that you are OK with changing the order of the list.

Follow the demo link below which shows that the above lambda sort in fact works on a small set of sample data.

Demo

Edit:

If you don't want to alter the original list, but instead want to just update the single matching Temp element, then you can make a copy of the list and then sort the copy:

List<Temp> copy = new ArrayList<>(list);
// sort copy, per above
// then update the original list
Temp match = copy.get(0);
int index = list.indexOf(match);
list.get(index).setFlag(true);

Upvotes: 0

Michael
Michael

Reputation: 44150

You can use ChronoUnit.DAYS.between to calculate the number of days between the dates, then use Stream.min to get the lowest value:

Optional<MyClass> shortestDate = myList.stream()
    .min(
        Comparator.comparingLong(
            item -> ChronoUnit.DAYS.between(item.asOfDate(), item.validFrom())
        )
    );

Upvotes: 1

Eugene
Eugene

Reputation: 120858

  temp.stream()
      .map(x -> new SimpleEntry<>(x, ChronoUnit.DAYS.between(x.getAsOfDate(), x.getValidFrom())))
      .min(Comparator.comparingLong(Entry::getValue))
      .map(Entry::getKey)
      .orElse(...);

Or simpler:

test.stream()
    .min(Comparator.comparingLong(x -> ChronoUnit.DAYS.between(x.asOfDate , x.validFrom)));

Upvotes: 3

Related Questions