diff --git a/guava-tests/test/com/google/common/collect/toImmutableRangeMapTest.java b/guava-tests/test/com/google/common/collect/toImmutableRangeMapTest.java new file mode 100644 index 000000000000..b1b226ae57b4 --- /dev/null +++ b/guava-tests/test/com/google/common/collect/toImmutableRangeMapTest.java @@ -0,0 +1,5 @@ +package com.google.common.collect; + +public class toImmutableRangeMapTest { + +} diff --git a/guava/src/com/google/common/collect/ImmutableRangeMap.java b/guava/src/com/google/common/collect/ImmutableRangeMap.java index 57b370e40552..5d6f73026166 100644 --- a/guava/src/com/google/common/collect/ImmutableRangeMap.java +++ b/guava/src/com/google/common/collect/ImmutableRangeMap.java @@ -35,6 +35,7 @@ import java.util.Map.Entry; import java.util.NoSuchElementException; import java.util.function.BiFunction; +import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.stream.Collector; import javax.annotation.CheckForNull; @@ -67,6 +68,67 @@ public class ImmutableRangeMap, V> implements RangeMap the type of input elements + * @param the key type of the map, extending Comparable + * @param the value type of the map + * @return a {@code Collector} that collects elements into a {@code ImmutableRangeMap} + */ + public static , V> Collector> toImmutableRangeMap( + Function> keyFunction, + Function valueFunction, + BinaryOperator mergeFunction) { + + return Collector.of( + TreeRangeMap::create, // Use type inference to create a TreeRangeMap instance. + (map, element) -> { + Range key = keyFunction.apply(element); + V value = valueFunction.apply(element); + + // Check for overlapping ranges + RangeMap overlappingMap = map.subRangeMap(key); + if (!overlappingMap.asMapOfRanges().isEmpty()) { + // If there are overlapping ranges, merge the values + for (Map.Entry, V> entry : overlappingMap.asMapOfRanges().entrySet()) { + V existingValue = entry.getValue(); + value = mergeFunction.apply(existingValue, value); + } + // Remove the original overlapping range + map.remove(key); + } + + map.put(key, value); + }, + (left, right) -> { + left.putAll(right); + return left; + }, + map -> { + ImmutableList.Builder> rangesBuilder = new ImmutableList.Builder<>(); + ImmutableList.Builder valuesBuilder = new ImmutableList.Builder<>(); + + // Iterate over all ranges in the map + for (Map.Entry, V> entry : map.asMapOfRanges().entrySet()) { + rangesBuilder.add(entry.getKey()); + valuesBuilder.add(entry.getValue()); + } + + // Construct an immutable ImmutableRangeMap. + return new ImmutableRangeMap<>(rangesBuilder.build(), valuesBuilder.build()); + } + ); + } + + + + + /** * Returns an empty immutable range map. *