Reputation: 3091
I decided to create a Map to store metric names and the Ranges representing live periods for each metric. At first I used a TreeRangeMap
to store the Ranges but since each Metric contains a single Range I switched to Ranges as shown below.
My goal is to keep the latest time range in the DEFAULT_METRICS_MAP when I receive a Range
for the metric from external API.
When I had a TreeRangeMap representing Ranges, comparing them was easy. I added new metric to the TreeRangeMap and then got the max range like this:
private static Optional<Range<Long>> maxRange(TreeRangeSet<Long> rangeSet) {
Set<Range<Long>> ranges = rangeSet.asRanges();
return ranges.stream().max(Comparator.comparing(Range::upperEndpoint));
}
What would be the correct way to compare Ranges when they are not wrapped into a TreeRangeMap?
public static final Map<String, Range<Long>> DEFAULT_METRICS_MAP;
static {
Map<String, Range<Long>> theMap = new HashMap<>();
theMap.put("Metric1", Range.closed(Long.MIN_VALUE, Long.MAX_VALUE));
theMap.put("Metric2", Range.closed(10L, 20L));
theMap.put("Metric3", Range.closed(30L, 50L));
METRICS_MAP = Collections.unmodifiableMap(theMap);
}
Upvotes: 2
Views: 977
Reputation: 7269
First of all it was a correct decission to avoid using TreeRangeMap/TreeRangeSet
in this particular case. As I understand (correct me if I'm wrong), you don't need to keep all the ranges for all the metrics. What you need is the latest range for each metric at every moment in time.
Ideally you would like to have a very fast method of retriving, like:
Range<Long> range = getRange(metric);
The most efficient way is to compare Range
objects on receiving them:
public void setRange(String metric, Range<Long> newRange) {
Range<Long> oldRange = metricRanges.get(metric);
if (comparator.compare(newRange, oldRange) > 0) {
metricRanges.put(metric, newRange);
}
}
Here is the full example:
// Better keep this map encapsulated
private final Map<String, Range<Long>> metricRanges = new HashMap<>();
private final Comparator<Range<Long>> comparator =
Comparator.nullsFirst(Comparator.comparing(Range::upperEndpoint));
static {
// Fill in your map with default ranges
}
public void setRange(String metric, Range<Long> newRange) {
Range<Long> oldRange = metricRanges.get(metric);
if (comparator.compare(newRange, oldRange) > 0) {
metricRanges.put(metric, newRange);
}
}
public Range<Long> getRange(String metric) {
return metricRanges.get(metric);
}
If you still need Optional
:
public Optional<Range<Long>> getRange(String metric) {
return Optional.of(metricRanges.get(metric));
}
Upvotes: 4