How to effectively traverse the Guava and TreeSet range?
I would like to take the intersection of a set and a range to get a set containing every item that is not in the range. For example, I would like to take set
and range
from the following piece of code:
import com.google.common.collect.*;
TreeSet<Integer> set = Sets.newTreeSet();
Collections.addAll(set, 1,2,3,5,11);
Range<Integer> range = Range.closed(4,10);
and return a new TreeSet containing only 5
source to share
In this particular example, you are better off not using Range
at all, but using set.subSet(4, true, 10, true)
directly, but presumably you have a more complex use case and your code is a simplified example.
In fact, there are not many alternatives, but for solving all cases. Part of the problem is that it NavigableSet
can use an arbitrary Comparator
, but Range
(intentionally) only works with the natural ordering of a value type, so it would be awkward to provide a method in Guava that takes arbitrary Range
a NavigableSet
and and intersects them.
The most general solution would look something like this:
if (range.hasLowerBound()) {
if (range.hasUpperBound()) {
return set.subSet(
range.lowerEndpoint(),
range.lowerBoundType() == BoundType.CLOSED,
range.upperEndpoint(),
range.upperBoundType() == BoundType.CLOSED);
} else {
return set.tailSet(
range.lowerEndpoint(),
range.lowerBoundType() == BoundType.CLOSED);
}
} else {
if (range.hasUpperBound()) {
return set.headSet(
range.upperEndpoint(),
range.upperBoundType() == BoundType.CLOSED);
} else {
return set;
}
}
However, it is worth mentioning that if you are not interested in efficiency, you can simply do Iterables.removeIf(set, Predicates.not(range))
or Sets.filter(set, range)
.
source to share