Get ActualDate or Previous date in a list of Objects

时间:2018-06-18 11:42:44

标签: java java-stream

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

1 个答案:

答案 0 :(得分:0)

我已经修改了你的Vehicle课程,因为我认为任何人都不应该在2018年使用过时的Date课程:

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.
}

假设您的列表已排序

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

在这种情况下,生成的numberOptionalInt[12]。其他结果:

  • 如果时间是01/01/2018 00:01:00,结果仍为OptionalInt[12]
  • 时间01/01/2018 00:10:00给出OptionalInt[10]
  • 时间01/02/2018 01:10:00。
  • 第一个列表元素之前的时间,例如01/01/1979 00:00:00,给出OptionalInt.empty。这是我想将结果作为OptionalInt给出的一个原因(另一个原因是考虑空列表)。

我不太清楚这是否比循环更好。你决定了。

如果您的列表很长(例如一百万辆车辆计数)您遇到性能问题,则需要使用二进制搜索。流将完全不适合此。你可以在其他地方阅读二进制搜索。

如果您无法确定列表是否已排序,则只需使用filter代替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);

链接: Oracle tutorial: Date Time解释如何使用java.time,我从Instant开始学习。{/ p>