【问题标题】:Calculate time between dates in list计算列表中日期之间的时间
【发布时间】:2015-10-29 14:45:03
【问题描述】:

我想使用 java 8 lambda 表达式计算 ArrayList 中日期之间的时间。我的意思是日期之间的时间:日期 i - 日期 i-1、日期 i-1 - 日期 i-2 等。我使用的是java.util.Date。

我已经在 java 7 中使用了这段代码,但我只是好奇流式传输是否可以缩短它:

List<Date> dates = transactions.stream().map(Transaction::getTimestampEnd).sorted((d1, d2) -> d1.compareTo(d2)).collect(Collectors.toList());
List<Long> interArrivalTimes = new ArrayList<>();
AtomicInteger counter = new AtomicInteger();
dates.forEach(d -> {

    int count = counter.getAndIncrement();
    if (count != 0) {

        Date previousDate = dates.get(count-1);
        long time = d.getTime()-previousDate.getTime();

        interArrivalTimes.add(time);
    }

});
double mean = interArrivalTimes.stream().mapToLong(i -> i).average().getAsDouble();

获得时差列表后,我想计算平均值。但更多的是关于我想缩短的循环部分。也许有减少或收集的东西?

非常感谢任何帮助!

【问题讨论】:

  • 几乎总是,当您在排序操作中引用 compareTo 方法时,例如在您的 .sorted((d1, d2) -&gt; d1.compareTo(d2)) 中,您可能会做一些过时的事情。当您的元素是Comparable 时,只需使用不带参数的sorted()。
  • 感谢您的评论!我会记住这一点。

标签: java date java-8 java-stream


【解决方案1】:

您可以流式传输索引而不是日期:

IntStream.range(1, dates.size())
        .mapToLong(i -> dates.get(i).getTime() - dates.get(i - 1).getTime())
        .average().getAsDouble();

或者使用一个很好的旧 for 循环:

LongStream.Builder b = LongStream.builder();
for (int i = 1; i < dates.size(); i++) {
  b.accept(dates.get(i).getTime() - dates.get(i - 1).getTime());
}
double mean = b.build().average().getAsDouble();

或者没有流:

double mean = 0;
for (int i = 1; i < dates.size(); i++) {
  mean += dates.get(i).getTime() - dates.get(i - 1).getTime();
}
if (!dates.isEmpty()) mean /= dates.size();

【讨论】:

  • 感谢您的回答!这是一个很好的解决方案。是否也可以通过流式传输和收集直接从日期列表中获取平均值(只是出于好奇,因为代码可能变得不可读)?
  • @bashoogzaad 您可能必须构建一个自定义收集器,如下所述:stackoverflow.com/a/30542049/829571
  • 流很棒,但它们不是这项工作的正确工具。一个简单的 for 循环确实是您想要的。这是一个常见的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 2022-01-05
  • 2021-01-16
  • 2010-11-07
相关资源
最近更新 更多