Guava 的 Ranges.asSet 输出无限列表
我正在尝试使用 Guava 的新 范围 功能,通过
Range<Date> dateRange = Ranges.range(start, BoundType.CLOSED, end, BoundType.CLOSED);
我的目标是获取此日期范围内的小时数。所以我创建了一个像这样的 DiscreteDomain:
private static final DiscreteDomain<Date> HOURS = new DiscreteDomain<Date>() {
public Date next(Date value) {
return addHours(value, 1);
}
private Date addHours(Date value, int i) {
Calendar cal = Calendar.getInstance();
cal.setTime(value);
cal.add(Calendar.HOUR_OF_DAY, i);
return cal.getTime();
}
public Date previous(Date value) {
return addHours(value, -1);
}
public long distance(Date start, Date end) {
Calendar cal1 = Calendar.getInstance();
cal1.setTime(start);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(end);
return cal2.getTimeInMillis() - cal1.getTimeInMillis();
}
public Date minValue() {
return new Date(Long.MIN_VALUE);
}
public Date maxValue() {
return new Date(Long.MAX_VALUE);
}
};
如果我只是输出输出,我会得到
[Thu Feb 24 00:00:00 EST 2011..Thu Feb 24 00:02:00 EST 2011]
我真的想在范围内每个小时看到的闭集,但是,所以我尝试一个 for 循环:
for (Date hour : hours) {
System.out.println(hour);
}
运行这个块时,我似乎得到一个无限的集合,从范围的左侧开始,但不在右侧停止,这让我杀死了 IDE。我做错了什么?
I am trying to get a date range using Guava's new Range functionality, via
Range<Date> dateRange = Ranges.range(start, BoundType.CLOSED, end, BoundType.CLOSED);
My goal is to get the hours in this date range. So I have created a DiscreteDomain like such:
private static final DiscreteDomain<Date> HOURS = new DiscreteDomain<Date>() {
public Date next(Date value) {
return addHours(value, 1);
}
private Date addHours(Date value, int i) {
Calendar cal = Calendar.getInstance();
cal.setTime(value);
cal.add(Calendar.HOUR_OF_DAY, i);
return cal.getTime();
}
public Date previous(Date value) {
return addHours(value, -1);
}
public long distance(Date start, Date end) {
Calendar cal1 = Calendar.getInstance();
cal1.setTime(start);
Calendar cal2 = Calendar.getInstance();
cal2.setTime(end);
return cal2.getTimeInMillis() - cal1.getTimeInMillis();
}
public Date minValue() {
return new Date(Long.MIN_VALUE);
}
public Date maxValue() {
return new Date(Long.MAX_VALUE);
}
};
If I merely sysout the output, I get the closed set
[Thu Feb 24 00:00:00 EST 2011..Thu Feb 24 00:02:00 EST 2011]
I really want to see each hour in the range, however, so I try a for loop:
for (Date hour : hours) {
System.out.println(hour);
}
When running this block, I seem to get an infinite set, beginning at the left side of the range, but not stopping at the right side, making me kill the IDE. What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为这可能是由于
ContigouslySet
返回的Iterator
的行为(由Range.asSet()
返回)造成的:它只停止当下一个计算值等于范围的右边界时。
就您而言,您是否尝试过使用
Thu Feb 24 02:00:00
而不是Thu Feb 24 00:02:00
作为范围的右边界来调用它?我认为这种行为是有问题的,可能值得询问是否可以更改
equalsOrThrow()
来检查left <= right
而不是left == right
另外,您的
distance()
方法不正确。根据方法契约,它应该以小时为单位返回距离,而不是以毫秒为单位。编辑 话
虽这么说,我相信真正的问题是,根据DiscreteDomain 的 javadoc:
在您的例子中,您试图在每小时日期上创建一个离散域,这是所有日期的部分域。我认为,这是问题的根本原因。当您有部分域时,
equalsOrThrow
方法变得不可靠,并且它可能“错过”范围的右边界。I think this might be due to the behavior of the
Iterator
returned by theContiguousSet
(returned byRange.asSet()
):It only stops when the next computed value is equal to the right bound of the range.
In your case, have you tried calling it using
Thu Feb 24 02:00:00
instead ofThu Feb 24 00:02:00
for the right bound of your range?I think this behavior is problematic, and it might be worth asking if
equalsOrThrow()
could be changed to check forleft <= right
instead ofleft == right
Also, your
distance()
method is incorrect. It should return the distance in hours, not in milliseconds, according to the method contract.EDIT
All this being said, I believe the real problem is that, according to the DiscreteDomain's javadoc:
In your case, you are attempting to create a discrete domain over hourly dates, which is a partial domain of all dates. This is, I think, the root cause of the problem. When you have a partial domain, the
equalsOrThrow
method becomes unreliable, and it can "miss" the right bound of your range.我刚刚尝试过这个,它对我来说效果很好。 @eneveu 也已经指出了您的
distance
方法的问题。我还猜测start
和end
之间存在毫秒级的细微差别,这意味着您永远不会真正获得Date
通过在start
上添加小时数等于end
。然而,这只是以不符合其设计目的的方式使用这些类的症状。
DiscreteDomain
的 Javadoc 指出:“小时”的
DiscreteDomain
并不代表所有可能的Date
对象的域,因此破坏了它的契约。I just tried this and it worked fine for me. @eneveu already pointed out the issue with your
distance
method as well. I'm also guessing that there's some minor difference at the millisecond level betweenstart
andend
which means that you'll never actually get aDate
equal toend
by adding hours tostart
.However, that's all just symptoms of using the classes in a way they aren't designed to work. The Javadoc for
DiscreteDomain
states:A
DiscreteDomain
of "hours" does not represent the domain of all possibleDate
objects and as such breaks its contract.