guava RangeMap
By traviscj
- 1 minutes read - 158 wordsWe had some code like this:
NavigableMap<Double, Integer> PRIORITY_MULTIPLIERS = new TreeMap<Double, Integer>() {{ "{{ " }}
put(LOW_THRESHOLD, 1); // (20k..40k) => 1
put(MEDIUM_THRESHOLD, 2); // [40k..100k) => 2
put(HIGH_THRESHOLD, 3); // [100k..+∞) => 3
}};
Integer getPriorityMultiplier(Double v) {
if (v < LOW_THRESHOLD) {
return 0;
}
return PRIORITY_MULTIPLIERS.floorEntry(v).getValue()
}
I replaced with a [RangeMap
][RangeMap] that uses [Range
][Range] instances as keys:
[RangeMap]: https://google.github.io/guava/releases/16.0/api/docs/com/google/common/collect/RangeMap.html
[Range]: https://google.github.io/guava/releases/16.0/api/docs/com/google/common/collect/Range.html
RangeMap<Double, Integer> PRIORITY_MULTIPLIERS = ImmutableRangeMap.<Double, Long>builder()
.put(Range.lessThan(LOW_THRESHOLD), 0)
.put(Range.closedOpen(LOW_THRESHOLD, MEDIUM_THRESHOLD), 1)
.put(Range.closedOpen(MEDIUM_THRESHOLD, HIGH_THRESHOLD), 2)
.put(Range.atLeast(HIGH_THRESHOLD), 3)
.build();
Integer getPriorityMultiplier(Double v) {
return rangePriorityMultipliers.get(v);
}
Advantages here being:
-
ImmutableRangeMap
explicitly checks for overlapping ranges, so specifyingRange.atMost
for the first range would fail at the time of instantiation. -
Puts declaration & endpoint behavior (open vs closed) together, instead of partly in the Map declaration and partly in the
map.floorEntry
call. -
Simple to test that entire range is covered:
@Test public void multipliersForEntireRange() { Set<Range<Double>> ranges = PRIORITY_MULTIPLIERS.asMapOfRanges().keySet(); ImmutableRangeSet<Double> rangeSet = ImmutableRangeSet.copyOf(ranges); assertThat(rangeSet.encloses(Range.all())).isTrue(); }