一、什么是TreeRangeSet?
TreeRangeSet是Guava中基于红黑树实现的区间集合。它专门用于处理区间的并集、交集、补集等数学运算,让复杂的区间逻辑变得简单直观。简单说,它就像是给区间运算装上了"数学大脑"!
二、为什么需要TreeRangeSet?
先来看个震撼对比:
传统区间判断:
java
// 判断时间是否在多个允许区间内
List<TimeRange> allowedRanges = Arrays.asList(
new TimeRange("09:00", "12:00"),
new TimeRange("14:00", "18:00"));
public boolean isAllowed(LocalTime time) {
for (TimeRange range : allowedRanges) {
if (range.contains(time)) {
return true;
}
}
return false; // O(n)时间复杂度,还要处理区间重叠!
}
使用TreeRangeSet:
java
RangeSet<LocalTime> allowedTimes = TreeRangeSet.create();
allowedTimes.add(Range.closedOpen(
LocalTime.of(9, 0), LocalTime.of(12, 0)));
allowedTimes.add(Range.closedOpen(
LocalTime.of(14, 0), LocalTime.of(18, 0)));
// 一行代码搞定!
boolean allowed = allowedTimes.contains(LocalTime.of(10, 30)); // true
// 自动处理区间合并:[9:00-12:00] ∪ [14:00-18:00]
数学般的优雅,这才是编程的艺术!
三、TreeRangeSet的核心设计思想
- 区间代数的编程实现

-
规范化的区间存储

-
基于红黑树的高效运算

四、TreeRangeSet的核心API详解
-
创建和基础操作
创建TreeRangeSet

添加和移除区间

-
查询操作
点查询

区间关系查询

-
集合运算
补集运算

子范围视图

区间视图操作

五、实际开发中的使用场景
场景一:数学区间运算引擎
java
/** * 数学区间运算引擎 - 使用TreeRangeSet实现复杂区间计算 */
public class MathIntervalEngine
{
private final RangeSet < Double > domain;
private final Map < String, RangeSet < Double >> namedSets;
public MathIntervalEngine()
{
this.domain = TreeRangeSet.create();
this.namedSets = new HashMap < > ();
// 默认定义实数域
domain.add(Range.all());
}
/** * 定义命名的区间集合 */
public void defineSet(String name, RangeSet < Double > set)
{
namedSets.put(name, set);
}
/** * 执行集合运算 */
public RangeSet < Double > evaluateExpression(String expression)
{
// 简单的表达式解析器(实际应用可以使用更复杂的解析器)
if (expression.contains("∪"))
{
String[] parts = expression.split("∪");
return union(evaluateExpression(parts[0].trim()), evaluateExpression(parts[1].trim()));
}
else if (expression.contains("∩"))
{
String[] parts = expression.split("∩");
return intersection(evaluateExpression(parts[0].trim()), evaluateExpression(parts[1].trim()));
}
else if (expression.contains("\\"))
{
String[] parts = expression.split("\\\\");
return difference(evaluateExpression(parts[0].trim()), evaluateExpression(parts[1].trim()));
}
else if (expression.startsWith("!"))
{
return complement(evaluateExpression(expression.substring(1).trim()));
}
else if (namedSets.containsKey(expression))
{
return namedSets.get(expression);
}
else
{
return parseRange(expression);
}
}
/** * 并集运算 */
public RangeSet < Double > union(RangeSet < Double > set1, RangeSet < Double > set2)
{
RangeSet < Double > result = TreeRangeSet.create(set1);
result.addAll(set2);
return result;
}
/** * 交集运算 */
public RangeSet < Double > intersection(RangeSet < Double > set1, RangeSet < Double > set2)
{
RangeSet < Double > result = TreeRangeSet.create(set1);
result.removeAll(set2.complement());
return result;
}
/** * 差集运算 */
public RangeSet < Double > difference(RangeSet < Double > set1, RangeSet < Double > set2)
{
RangeSet < Double > result = TreeRangeSet.create(set1);
result.removeAll(set2);
return result;
}
/** * 补集运算 */
public RangeSet < Double > complement(RangeSet < Double > set)
{
return set.complement();
}
/** * 解析区间表达式 */
private RangeSet < Double > parseRange(String expression)
{
try
{
if (expression.equals("R"))
{
RangeSet < Double > realNumbers = TreeRangeSet.create();
realNumbers.add(Range.all());
return realNumbers;
}
// 解析类似 "[1, 5]" "(2, 8)" 的表达式
expression = expression.trim();
char leftBracket = expression.charAt(0);
char rightBracket = expression.charAt(expression.length() - 1);
String[] parts = expression.substring(1, expression.length() - 1).split(",");
double lower = Double.parseDouble(parts[0].trim());
double upper = Double.parseDouble(parts[1].trim());
Range < Double > range;
if (leftBracket == '[' && rightBracket == ']')
{
range = Range.closed(lower, upper);
}
else if (leftBracket == '(' && rightBracket == ')')
{
range = Range.open(lower, upper);
}
else if (leftBracket == '[' && rightBracket == ')')
{
range = Range.closedOpen(lower, upper);
}
else if (leftBracket == '(' && rightBracket == ']')
{
range = Range.openClosed(lower, upper);
}
else
{
throw new IllegalArgumentException("无效的区间表达式: " + expression);
}
RangeSet < Double > result = TreeRangeSet.create();
result.add(range);
return result;
}
catch (Exception e)
{
throw new IllegalArgumentException("无法解析区间表达式: " + expression, e);
}
}
/** * 计算区间的度量(长度) */
public double measure(RangeSet < Double > set)
{
return set.asRanges().stream() .mapToDouble(range - >
{
if (!range.hasLowerBound() || !range.hasUpperBound())
{
return Double.POSITIVE_INFINITY;
}
return range.upperEndpoint() - range.lowerEndpoint();
}) .sum();
}
/** * 检查集合关系 */
public SetRelation checkRelation(RangeSet < Double > set1, RangeSet < Double > set2)
{
boolean subset = set1.enclosesAll(set2);
boolean superset = set2.enclosesAll(set1);
boolean disjoint = !set1.intersects(set2);
if (subset && superset)
{
return SetRelation.EQUAL;
}
else if (subset)
{
return SetRelation.SUBSET;
}
else if (superset)
{
return SetRelation.SUPERSET;
}
else if (disjoint)
{
return SetRelation.DISJOINT;
}
else
{
return SetRelation.OVERLAP;
}
}
/** * 求解不等式系统 */
public RangeSet < Double > solveInequalitySystem(List < String > inequalities)
{
RangeSet < Double > solution = TreeRangeSet.create();
solution.add(Range.all());
// 初始化为全体实数
for (String inequality: inequalities)
{
RangeSet < Double > inequalitySet = parseInequality(inequality);
solution = intersection(solution, inequalitySet);
}
return solution;
}
private RangeSet < Double > parseInequality(String inequality)
{
inequality = inequality.trim();
RangeSet < Double > result = TreeRangeSet.create();
if (inequality.contains(">="))
{
String[] parts = inequality.split(">=");
double value = Double.parseDouble(parts[1].trim());
result.add(Range.atLeast(value));
}
else if (inequality.contains("<="))
{
String[] parts = inequality.split("<=");
double value = Double.parseDouble(parts[1].trim());
result.add(Range.atMost(value));
}
else if (inequality.contains(">"))
{
String[] parts = inequality.split(">");
double value = Double.parseDouble(parts[1].trim());
result.add(Range.greaterThan(value));
}
else if (inequality.contains("<"))
{
String[] parts = inequality.split("<");
double value = Double.parseDouble(parts[1].trim());
result.add(Range.lessThan(value));
}
else if (inequality.contains("="))
{
String[] parts = inequality.split("=");
double value = Double.parseDouble(parts[1].trim());
result.add(Range.singleton(value));
}
return result;
}
/** * 生成区间可视化描述 */
public String visualize(RangeSet < Double > set, double from, double to, int width)
{
StringBuilder sb = new StringBuilder();
sb.append("数轴: ").append(from).append(" 到 ").append(to).append("\n");
double step = (to - from) / width;
for (int i = 0; i <= width; i++)
{
double x = from + i * step;
if (set.contains(x))
{
sb.append("█");
}
else
{
sb.append(" ");
}
}
sb.append("\n刻度: ");
for (int i = 0; i <= width; i += width / 10)
{
double x = from + i * step;
sb.append(String.format("%.1f ", x));
}
return sb.toString();
}
// 集合关系枚举
public enum SetRelation
{
EQUAL, SUBSET, SUPERSET, DISJOINT, OVERLAP
}
/** * 演示复杂的区间运算 */
public void demonstrateComplexOperations()
{
// 定义几个集合
defineSet("A", parseRange("[0, 5]"));
defineSet("B", parseRange("[3, 8]"));
defineSet("C", parseRange("[1, 10]"));
// 执行复杂运算: (A ∪ B) ∩ !C
RangeSet < Double > result = evaluateExpression("(A ∪ B) ∩ !C");
System.out.println("A = " + namedSets.get("A"));
System.out.println("B = " + namedSets.get("B"));
System.out.println("C = " + namedSets.get("C"));
System.out.println("(A ∪ B) ∩ !C = " + result);
System.out.println("度量: " + measure(result)); // 可视化结果
System.out.println(visualize(result, -2, 12, 80));
}
}