Defozo Defozo - 2 months ago 6
Java Question

Is there a way to have a map like ArrayListMultimap but with RangeSet and "coalescing" instead?

I want a map which assignes RangeSets to Integers in a way that instead of:

Map<Integer, RangeSet> sensorIDsWithTimeRange = new HashMap<>();
if (sensorIDsWithTimeRange.containsKey(sensorId)) {
sensorIDsWithTimeRange.get(sensorId).add(Range.closedOpen(startTime, endTime));
} else {
RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closedOpen(startTime, endTime));
sensorIDsWithTimeRange.put(sensorId, rangeSet);
}


I would write just:

sensorIDsWithTimeRange.put(sensorId, Range.closedOpen(startTime, endTime));


And it would create a new key if the key not already exists or insert new range to already existing RangeSet and coalescent it if the key exists.

Answer

You can use java.util.AbstractMap to quickly create your own custom Map type:

public class RangeSetHashMap<K, V extends Comparable> extends AbstractMap<K, RangeSet<V>> {
    private final Map<K, RangeSet<V>> map = new HashMap<>();

    public RangeSet<V> put(K key, Range<V> value) {
        RangeSet<V> rangeSet = computeIfAbsent(key, k -> TreeRangeSet.create());
        rangeSet.add(value);
        return rangeSet;
    }

    @Override
    public RangeSet<V> put(K key, RangeSet<V> value) {
        return map.put(key, value);
    }

    @Override
    public Set<Entry<K, RangeSet<V>>> entrySet() {
        return map.entrySet();
    }
}

Example usage:

RangeSetHashMap<Integer, Time> sensorIDsWithTimeRange = new RangeSetHashMap<>();
sensorIDsWithTimeRange.put(0, Range.closedOpen(valueOf("12:30:00"), valueOf("12:40:00")));
sensorIDsWithTimeRange.put(0, Range.closedOpen(valueOf("17:09:42"), valueOf("23:06:33")));
sensorIDsWithTimeRange.put(1, Range.closedOpen(valueOf("04:13:56"), valueOf("04:14:02")));
System.out.println(sensorIDsWithTimeRange);
sensorIDsWithTimeRange.put(0, Range.closedOpen(valueOf("02:11:12"), valueOf("12:45:19")));
System.out.println(sensorIDsWithTimeRange);

Example output:

{0=[[12:30:00‥12:40:00), [17:09:42‥23:06:33)], 1=[[04:13:56‥04:14:02)]}
{0=[[02:11:12‥12:45:19), [17:09:42‥23:06:33)], 1=[[04:13:56‥04:14:02)]}
Comments