How to intersect a Guava Range and a TreeSet efficiently?
guava, java
Solution
In this particular example, you're better off not using `Range` at all, but using `set.subSet(4, true, 10, true)` directly, but presumably you have a more complicated use case, and your code is a simplified example.
There's really not much alternative but to deal with all the cases yourself. Part of the problem is that a `NavigableSet` can use an arbitrary `Comparator`, but `Range` (deliberately) works only with the natural ordering of the value type, so it'd be somewhat awkward to provide a method in Guava that takes an arbitrary `Range` and a `NavigableSet` and intersects them.
The most general solution would look something like...
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;
}
}
That said, it's worth mentioning that if you're not concerned about efficiency, you can just do `Iterables.removeIf(set, Predicates.not(range))` or `Sets.filter(set, range)`.
Problem
I'd like to take the intersection of a set and a range, so that I get a set containing every element that is not in the range. For example, I'd like a way to take `set` and `range` from the following code snippet: ``` 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 just `5`