Java 8 counting in a period of sliding window

问题: Given the following class and data structure below, I want to calculate the sum of count for each consecutive 3 hours sliding window similar to following results: public...

问题:

Given the following class and data structure below, I want to calculate the sum of count for each consecutive 3 hours sliding window similar to following results:

public class Log {
    private int id;
    private LocalDateTime timestamp;
    private int count;
}
id   timestamp               count
1    2018-10-10T08:00:00     12
2    2018-10-10T08:30:00     5
3    2018-10-10T08:45:00     7
4    2018-10-10T09:10:00     9
5    2018-10-10T09:50:00     3
6    2018-10-10T10:15:00     8
7    2018-10-10T12:00:00     6
8    2018-10-10T12:30:00     1
9    2018-10-10T12:45:00     2
10   2018-10-10T17:30:00     4
11   2018-10-10T17:35:00     7

The log's timestamp is in ascending order, and sum the total of count for each 3 hours window (can cross different day) from the first record. The result would be:

2018-10-10T08:00:00 ~ 2018-10-10T10:59:00   12+5+7+9+3+8
2018-10-10T08:30:00 ~ 2018-10-10T11:29:00   5+7+9+3+8
2018-10-10T08:45:00 ~ 2018-10-10T11:44:00   7+9+3+8
2018-10-10T09:10:00 ~ 2018-10-10T12:09:00   9+3+8+6
2018-10-10T09:50:00 ~ 2018-10-10T12:09:00   3+8+6+1
2018-10-10T10:15:00 ~ 2018-10-10T13:14:00   8+6+1+2
...

I have some sample code below but feel it is not so efficient (if there are huge amount of logs) as each time I have to get and compare filtered timestamp from all logs. How can I only compare from the current logs until the end?

var logs = List.of();
logs.stream.map(log -> {
    var start = log.getTimeStamp();
    var end = log.getTimeStamp().plusHours(3);
    var logsWithinWindow = logs.stream().filter(l -> isWithinRange(start, end, l.getTimeStamp()));
    return logsWithinWindow.map(Log::getCount).sum();
});

回答1:

If you were to count the logs in any duration, you could have used :

int countLogsInDuration(List<Log> logs, LocalDateTime start, LocalDateTime end) {
    return logs.stream()
            .filter(log -> isWithinRange(log.getTimeStamp(), start, end))
            .mapToInt(Log::getCount)
            .sum();
}

which relies on

private static boolean isWithinRange(LocalDateTime logTimestamp, LocalDateTime start, LocalDateTime end) {
    // return true or false based on comparison
}

Also, computing logs for every 3 hours window at least in your case seems redundant as your sliding window size is 30 mins. You can hence compute count for every 30 mins such as 8:00 to 8:30, then 8:30 to 9:00 and so on so forth. This would give avoid redundantly computed count while your sliding window overlaps with previous duration.

  • 发表于 2019-03-11 02:21
  • 阅读 ( 203 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除