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`

Original source