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

+3


source to share


1 answer


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)

.

+10


source







All Articles