I have a list of intervals with integer values [eg. [1, 4], [10, 19] etc.]. Is there a way to put these intervals into some java collections' container [eg. Set] such that I can call a 'union' function on the container. The 'union' function should give me a list of intervals such that if any 2 inserted intervals overlap then they should be merged in the output. I tried using the Range class in Guava but ended up comparing all the intervals against each other before merging. An elegant approach to this would be really appreciated ! Here is what I have tried based on the response below. The output is [[1, 15], [17, 20]], which is correct. I wanted to know if there is some exiting API which implements something like this.
public static void main(String[] args) {
// mock data
List<MyIntRange> rng_lst = new ArrayList<Junk.MyIntRange>();
rng_lst.add(new MyIntRange(1, 10));
rng_lst.add(new MyIntRange(5, 15));
rng_lst.add(new MyIntRange(17, 20));
// sort intervals by start position
Collections.sort(rng_lst);
// merge the intervals which overlap
List<MyIntRange> res_lst = new ArrayList<Junk.MyIntRange>();
MyIntRange old_rng = null;
for (MyIntRange cur_rng : rng_lst) {
if (old_rng == null) {
old_rng = cur_rng;
} else {
if (old_rng.rng.upperEndpoint() < cur_rng.rng.lowerEndpoint()) {
// this does not over lap with the next one
res_lst.add(old_rng);
old_rng = cur_rng;
} else {
// overlap
old_rng = new MyIntRange(old_rng.rng.lowerEndpoint(),
cur_rng.rng.upperEndpoint());
}
}
}
// add the last range
res_lst.add(old_rng);
// done!
System.out.println(res_lst);
}
// wrapper around Guava's Range to make it comparable based on the
// interval's start
public static class MyIntRange implements Comparable<MyIntRange> {
Range<Integer> rng;
public MyIntRange(int start, int end) {
rng = Ranges.closed(start, end);
}
public int compareTo(MyIntRange that) {
int res = -1;
if (this.rng.lowerEndpoint() > that.rng.lowerEndpoint()) {
res = 1;
}
return res;
}
public String toString() {
return "[" + rng.lowerEndpoint() + ", " + rng.upperEndpoint() + "]";
}
}
thanks
Intervals are implemented as half-open, which is to say that the start instant is inclusive but the end instant is exclusive. The end is always greater than or equal to the start. The interval is also restricted to just one chronology and time zone.
Use: dateTime. minusSeconds(int sec); method to substract your interval.
This is basically exactly what RangeSet
does in the just-released Guava 14.0, except it does the merging for you, rather than telling you which ranges could be merged.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With