我有一个句点列表 - 每个句点包含startTime和endTime(作为时间戳)。 我想创建一个列表,其中包含给定范围内的缺失空白。
实施例:
从100
到500
获取给定列表:
Range[150, 200]
Range[230, 400]
它会产生一个列表:
Range[100, 150]
Range[200, 230]
Range[400, 500]
我创建了一个简单的算法,它迭代我的输入列表并创建有效的结果表,但我想知道我是否可以使用java8
时间API做同样的事情,或者是否有一个外部库。
答案 0 :(得分:4)
使用单个范围边界的列表,您可以使用包含min和max的完整集来构造它:
我正在使用array [int,int],它应该很容易翻译成你的Range
对象。
逻辑很简单:只使用范围边界数,制作一个完整的集合,然后制作所有连续边界的对。为此,首先创建所有(不同)数字的排序列表,包括缺失的范围......
List<Integer> flat = Arrays.<int[]>asList(new int[] { 150, 200 },
new int[] { 230, 400 }).stream()
.flatMap(e -> Arrays.asList(e[0],
e[1]).stream()).collect(Collectors.toList());
List<Integer> fullRange = new ArrayList<>();
fullRange.add(100);
fullRange.add(500);
fullRange.addAll(flat);
List<Integer> all = fullRange.stream()
.distinct()
.sorted()
.collect(Collectors.toList());
System.out.println(
IntStream.range(0, all.size())
.filter(i -> i < -1 + all.size()) #Excluding the last element
.mapToObj(index -> Arrays.asList( //You can create Range objects here
all.get(index),
all.get(index + 1))
)
.collect(Collectors.toList()));
输出:
[[100, 150], [150, 200], [200, 230], [230, 400], [400, 500]]
答案 1 :(得分:2)
这是使用我的lib Time4J的解决方案。我假设您的时间戳将被建模为“自Unix纪元以来的毫秒”,但您可以自由使用任何其他类型。 Time4J知道许多不同类型的与日期或时间相关的区间,并提供了各种方法来计算区间的干扰,这里是complement of an interval collection。
// define/create your intervals
MomentInterval i1 =
MomentInterval.between(Instant.ofEpochMilli(150), Instant.ofEpochMilli(200));
MomentInterval i2 =
MomentInterval.between(Instant.ofEpochMilli(230), Instant.ofEpochMilli(400));
// collect the intervals into an interval-collection
IntervalCollection<Moment> ic =
IntervalCollection.onMomentAxis().plus(Arrays.asList(i1, i2));
// define/create the outer time window
MomentInterval window =
MomentInterval.between(Instant.ofEpochMilli(100), Instant.ofEpochMilli(500));
// create/calculate the complement of the interval collection
ic.withComplement(window)
.getIntervals()
.forEach(
i ->
System.out.println(
"Range["
+ i.getStart().getTemporal().toTemporalAccessor().toEpochMilli()
+ ", "
+ i.getEnd().getTemporal().toTemporalAccessor().toEpochMilli()
+ "]"
)
);
范围[100,150]
范围[200,230]
范围[400,500]
顺便说一句,Time4J使用半开方法进行时刻/瞬时间隔,这意味着排除了这些间隔的结束边界。因此,我宁愿选择开括号“)”而不是“]”,但这里已经密切关注你的问题了。
答案 2 :(得分:0)
另一种解决方案可能如下所示。为此,我定义了一些类和函数。
班级范围:
class Range{
private int start;
private int end;
}
类RangeInfo :
class RangeInfo {
private List<Range> ranges;
private int newStart;
private int newEnd;
}
<强>功能1:强>
此函数从两个Range
对象创建新的Range
对象。
BiFunction<Range,Range,Range> function1 = (r1,r2)->new Range(r1.getEnd(),r2.getStart());
功能
此函数有两个参数:List (Range[150, 200] and Range[230, 400])
和Range (100, 500)
,并返回新范围列表。
BiFunction<List<Range>,Range,List<Range>> function = (r1, pair)->{ // you can use new Pair(100,500) instead of Range object
result.add(new Range(pair.getStart(),r1.get(0).getStart()));
IntStream.range(0, r1.size() - 1).mapToObj(i -> function1.apply(r1.get(i), r1.get(i + 1))).forEachOrdered(result::add);
result.add(new Range(r1.get(r1.size()-1).getEnd(),pair.getEnd()));
result.addAll(r1);
return result;
};
最后创建Range并对其进行排序,如下所示。
function.apply(ranges,new Range(100,500))
.stream()
.sorted(Comparator.comparingInt(Range::getStart))
.collect(Collectors.toList());