-1

I have a class with the following implementation.

class Vehicle {
private Date date;
private int nbOfVehicleArriving;

   public Vehicle(Date date, int nbOfVehicleArriving) {
    this.date = date;
    this.nbOfVehicleArriving = nbOfVehicleArriving;
   }

   public int getNbOfVehicleArriving() {
    return nbOfVehicleArriving;
   }
}

I have list of this objects.I need to get the date equal or before dateTime to display the int value

01/01/2018 00:00:00 12
01/01/2018 00:10:00 10
01/01/2018 01:00:00 5
01/01/2018 01:10:00 10

Example :

01/01/2018 00:00:00 will give me 12
01/01/2018 00:01:00 will give me 12
01/01/2018 00:10:00 10 will give me 10
01/02/2018 01:10:00 10 (last value known : 10)

I know I can do a for loop, but is it the best way?

Thanks

testeurFou
  • 71
  • 3
  • 11
  • Anyway you have to iterate the Vehicle Collection. If you have big number of objects, consider using some sort of database. Filtering there will be done faster because of using indicies. – Sergei Podlipaev Jun 18 '18 at 11:45
  • 1
    Provide us the`for-loop` to demonstrate your goal. This explanation is yet a bit unclear. – Nikolas Charalambidis Jun 18 '18 at 11:52
  • Duplicate: https://stackoverflow.com/questions/494180/java-how-do-i-check-if-a-date-is-within-a-certain-range https://stackoverflow.com/questions/2592501/how-to-compare-dates-in-java – Francois Du Toit Jun 18 '18 at 11:53
  • Since you tagged java-stream: You may use a stream. Filter on date before or on actual date and then take the max date. Whether it’s better is probably a matter of taste. However, the `Date` class is long outdated, you may well prefer to use `Instant` or another class from [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jun 18 '18 at 12:29

1 Answers1

0

I have modified your Vehicle class a bit since I don’t think anyone should use the long outdated Date class in 2018:

public class Vehicle {
    public static final ZoneId TIME_ZONE = ZoneId.of("Europe/Nicosia");
    public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss");

    private Instant date;
    private int nbOfVehicleArriving;

    public Vehicle(String date, int nbOfVehicleArriving) {
        this.date = LocalDateTime.parse(date, FORMATTER).atZone(TIME_ZONE).toInstant();
        this.nbOfVehicleArriving = nbOfVehicleArriving;
    }

    // getters etc.
}

Assuming your list is sorted

    Instant time = LocalDateTime.parse("01/01/2018 00:00:00", Vehicle.FORMATTER)
            .atZone(Vehicle.TIME_ZONE)
            .toInstant();
    OptionalInt number = myList.stream()
            .takeWhile(v -> !v.getDate().isAfter(time))
            .max(Comparator.comparing(Vehicle::getDate))
            .map(v -> OptionalInt.of(v.getNbOfVehicleArriving()))
            .orElseGet(OptionalInt::empty);

The resulting number in this case is OptionalInt[12]. Other results:

  • If the time is 01/01/2018 00:01:00, the result still is OptionalInt[12].
  • Time 01/01/2018 00:10:00 gives OptionalInt[10].
  • So does time 01/02/2018 01:10:00.
  • A time before the first list element, for example 01/01/1979 00:00:00, gives OptionalInt.empty. This was one reason I wanted to give the result as an OptionalInt (the other was to take an empty list into account).

It is not very clear to me whether this is better than a loop. You decide.

If your list is very long (for example a million vehicle counts) and you experience performance problems, you will want to use a binary search. A stream would be completely unsuited for this. You can read about binary search elsewhere.

If you cannot be sure that the list is sorted you just need to use filter instead of takeWhile:

    OptionalInt number = myList.stream()
            .filter(v -> !v.getDate().isAfter(time))
            .max(Comparator.comparing(Vehicle::getDate))
            .map(v -> OptionalInt.of(v.getNbOfVehicleArriving()))
            .orElseGet(OptionalInt::empty);

Link: Oracle tutorial: Date Time explaining how to use java.time, where I took the Instant class from.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161