确定具有 java 8 个流 api 的对象之间的关系

Determine relationship between objects with java 8 streams api

最近我解决了以下问题:

给定一个按时间顺序排列的 LocalDateTime 列表,找出邻居之间的平均持续时间。

我做了以下事情:

@Test
public void canCalculateAverageDuration() {
    final LocalDateTime now = LocalDateTime.now();
    final List<LocalDateTime> localDateTimes = Arrays.asList(now, now.minusHours(5), now.plusMinutes(2));

    final List<Duration> durations = new ArrayList<>();
    localDateTimes.stream()
        .sorted()
        .reduce((first, second) -> {
            durations.add(Duration.between(first, second));
            return second;
        });

    final OptionalDouble averageNanos = durations.stream()
            .mapToDouble(Duration::toNanos)
            .average();

    final Duration average = Duration.ofNanos((long) averageNanos.orElse(0.0));
    assertThat(average).isEqualTo(Duration.parse("PT2H31M"));
}

我想知道这个问题是否可以用更优雅的方式解决,例如:我想尽可能避免使用持续时间列表。你怎么看?

您只需使用迭代(即不使用 Streams)即可解决此问题:

@Test
public void canCalculateAverageDuration() {
  final LocalDateTime now = LocalDateTime.now();
  final List<LocalDateTime> localDateTimes = Arrays.asList(
      now,
      now.minusHours(5),
      now.plusMinutes(2)
  );
  localDateTimes.sort(Comparator.naturalOrder());

  LocalDateTime previous = null;
  LongSummaryStatistics stats = new LongSummaryStatistics();
  for (LocalDateTime dateTime : localDateTimes) {
    if (previous == null) {
      previous = dateTime;
    }
    else {
      stats.accept(Duration.between(previous, dateTime).toNanos());
    }
  }

  final Duration average = Duration.ofNanos((long) Math.ceil(stats.getAverage()));

  assertThat(average).isEqualTo(Duration.parse("PT2H31M"));
}

这个是不是更优雅,看个人喜好,但是这个版本至少没有使用中间集合

我刚找到这个:

Collections.sort(localDateTimes);
final double average = IntStream.range(0, localDateTimes.size() - 1)
    .mapToLong(l ->
        Duration.between(
            localDateTimes.get(l),
            localDateTimes.get(l+1))
        .toNanos())
    .average().orElse(0.0);
assertThat(Duration.ofNanos((long) average)).isEqualTo(Duration.parse("PT2H31M"));