确定具有 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"));
最近我解决了以下问题:
给定一个按时间顺序排列的 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"));