有一个包含按时间排列的数据集的远程资源,数据是静态的,不会改变。每当我们要从那里获取任何东西时,我们都会将其保存在缓存中。用户可以请求特定时间段的数据,比方说从2019年1月1日到2020年1月1日。如果没有缓存数据,那么我们就从远程资源请求数据,如果只有一部分数据被缓存,那么我们需要请求丢失的数据。有一个计算缺失间隔的函数,我认为它看起来太冗长了。最好能得到一些更好的解决方案的建议。谢谢。
@SneakyThrows
public static ArrayList<TimeSpan> difference(TimeSpan requested, TimeSpan cached){
ArrayList<TimeSpan> missingIntervals = new ArrayList<>();
//requested period is within cached
if (requested.getFrom().compareTo(cached.getFrom()) >= 0 && requested.getTo().compareTo(cached.getTo()) <= 0){
missingIntervals = null;
//requested period is before or after cached
} else if (requested.getTo().compareTo(cached.getFrom()) <= 0 || requested.getFrom().compareTo(cached.getTo()) >= 0){
missingIntervals.add(requested);
// requested start and end dates are outside of cached range
} else if (requested.getFrom().compareTo(cached.getFrom()) <= 0 && requested.getTo().compareTo(cached.getTo()) >= 0){
missingIntervals.add(new TimeSpan(requested.getFrom(),cached.getFrom()));
missingIntervals.add(new TimeSpan(cached.getTo(),requested.getTo()));
// requested start date is before cached period
} else if (requested.getFrom().compareTo(cached.getFrom()) < 0
&& requested.getTo().compareTo(cached.getTo()) <= 0
&& requested.getTo().compareTo(cached.getFrom()) > 0){
missingIntervals.add(new TimeSpan(requested.getFrom(),cached.getFrom()));
// requested end date is after cached period
} else if (requested.getTo().compareTo(cached.getTo()) >= 0
&& requested.getFrom().compareTo(cached.getFrom()) >= 0
&& requested.getFrom().compareTo(cached.getTo()) < 0){
missingIntervals.add(new TimeSpan(cached.getTo(),requested.getTo()));
}
return missingIntervals;
}
下面是一个TimeSpan类:
public class TimeSpan {
public TimeSpan(Date from, Date to) throws Exception{
if(from.compareTo(to) >= 0){
throw new Exception("Start date cannot be greater then end date");
}
this.from = from;
this.to = to;
}
private final Date from;
private final Date to;
}
发布于 2020-12-01 17:42:36
我建议将这个方法移到TimeSpan
类中。让一个TimeSpan
告诉你它的重叠。不要询问它的内部细节,然后自己想办法解决。私有助手方法将使compareTo
调用更具可读性。
各种各样的其他想法:
检查过的异常可能不在这里。我建议选择IllegalArgumentException
,因为这就是问题所在。强烈建议使用比Exception
更具体的异常。
尽早返回比分配返回值更好,并且只返回一次。这是C
的一个保留,后者只允许一次返回。
当您不关心所使用的列表类型时,通常最好使用List
变量类型。
传统上,变量定义在类的顶部,而不是底部。
传统上,空白是在if
和(
之间以及)
和{
之间添加的。
Date
类已经有了一个after()
方法,这将使TimeSpan
构造函数更加简洁。
构造函数中的错误消息不正确。“开始日期”也不能等于“截止日期”。
您应该强烈考虑使用java.time
而不是java.util
时间类。他们实际上遭到了反对。
返回null
可能比返回一个空集合更糟糕,尽管在没有看到客户端代码的情况下很难权威地这样说。
如果您做了所有这些更改,您的代码可能如下所示:
public final class TimeSpan {
private final Date from;
private final Date to;
public TimeSpan(Date from, Date to) throws IllegalArgumentException {
if (!from.before(to)) {
throw new IllegalArgumentException("Start date cannot be greater than or equal to end date");
}
this.from = from;
this.to = to;
}
/**
* Subtracts the timeSpan argument from this TimeSpan. This will result in a list of between
* zero and two TimeSpans, ordered by start time.
* @param timeSpan the span to subtract from this timespan. May not be null.
* @return a list of TimeSpans covering the time that is in this timespan and not the argument timespan. Will
* never return null.
*/
public List<TimeSpan> minus(TimeSpan timeSpan) {
// This TimeSpan is completely inside the argument.
if (timeSpan.contains(this.from) && timeSpan.contains(this.to)) {
return Collections.emptyList();
}
// This TimeSpan is either fully before or fully after argument
if (this.endsBeforeOrAt(timeSpan) || this.startsAfterOrAt(timeSpan)) {
return listOf(this); // only OK because this class is immutable
}
// This TimeSpan starts before and ends inside the argument
if (timeSpan.contains(this.to)) {
return listOf(new TimeSpan(this.from, timeSpan.from));
}
// This TimeSpan starts inside and ends after argument
if (timeSpan.contains(this.from)) {
return listOf(new TimeSpan(timeSpan.to, this.to));
}
// This TimeSpan starts before and ends after argument
List<TimeSpan> results = new ArrayList<>();
results.add(new TimeSpan(this.from, timeSpan.from));
results.add(new TimeSpan(timeSpan.to, this.to));
return results;
}
private boolean endsBeforeOrAt(TimeSpan timeSpan) {
return this.to.compareTo(timeSpan.from) <= 0;
}
private boolean startsAfterOrAt(TimeSpan timeSpan) {
return this.from.compareTo(timeSpan.to) >= 0;
}
private boolean contains(Date date) {
return (this.from.compareTo(date) >= 0) && (this.to.compareTo(date) <= 0);
}
// If you're using Guava, replace this with Lists.of()
private static List<TimeSpan> listOf(TimeSpan timeSpan) {
List<TimeSpan> results = new ArrayList<>();
results.add(timeSpan);
return results;
}
}
https://codereview.stackexchange.com/questions/252905
复制