Недавно я решил следующую проблему:
Учитывая хронологически упорядоченный список 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"));
}
Интересно, можно ли решить проблему более элегантным способом, например: я бы хотел по возможности избегать списка длительностей. Что вы думаете?
2 ответа
Я только что нашел это:
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"));
Вы можете решить эту проблему, просто используя итерации (т.е. не используя потоки):
@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"));
}
Будет ли это более элегантным, зависит от личных предпочтений, но эта версия по крайней мере не использует промежуточных коллекций.
Похожие вопросы
Новые вопросы
java
Java - это язык программирования высокого уровня. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег редко используется отдельно и чаще всего используется вместе с [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] и [maven].