如何解决番石榴的Ranges.asSet输出无限列表
|| 我正在尝试使用Guava的新Range功能通过以下方式获取日期范围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);
}
};
如果我仅对输出进行sysout,则会得到封闭集
[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。我究竟做错了什么?
解决方法
我认为这可能是由于
ContiguousSet
返回的Iterator
的行为(由Range.asSet()
返回)造成的:
@Override public UnmodifiableIterator<C> iterator() {
return new AbstractLinkedIterator<C>(first()) {
final C last = last();
@Override
protected C computeNext(C previous) {
return equalsOrThrow(previous,last) ? null : domain.next(previous);
}
};
}
private static boolean equalsOrThrow(Comparable<?> left,@Nullable Comparable<?> right) {
return right != null && compareOrThrow(left,right) == 0;
}
private static int compareOrThrow(Comparable left,Comparable right) {
return left.compareTo(right);
}
仅当下一个计算值等于范围的右边界时,它才会停止。
在您的情况下,您是否尝试过使用Thu Feb 24 02:00:00
而不是Thu Feb 24 00:02:00
来表示范围的右边界?
我认为这种行为是有问题的,可能值得一问的是,是否可以将equalsOrThrow()
更改为left <= right
而不是left == right
另外,您的distance()
方法不正确。根据方法合同,它应该以小时为单位返回距离,而不是以毫秒为单位。
编辑
综上所述,我相信真正的问题是,根据DiscreteDomain的javadoc:
离散域始终代表
其类型的整个值集;
它不能代表部分域名
例如\“素数整数\”或\“字符串
长度为5。“
在您的情况下,您尝试在每小时的日期上创建一个离散域,这是所有日期的部分域。我认为,这是问题的根本原因。当您拥有部分域时,equalsOrThrow
方法将变得不可靠,并且可能会“错过”范围的右边界。
, 我只是尝试了一下,对我来说效果很好。 @eneveu也已经指出了您的distance
方法的问题。我还猜测start
和end
之间在毫秒级上会有一些细微的差异,这意味着通过将hours16ѭ加几个小时,您将永远不会得到等于end
的Date
。
但是,这仅仅是使用类的目的而不是其正常工作的症状。 doc21ѭ的Javadoc指出:
离散域始终代表其类型的整个值集;它不能表示部分域,例如\“素数整数\”或\“长度为5的字符串\”
\“ hours \”的DiscreteDomain
并不代表所有可能的Date
对象的域,因此违反了合同。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。