Java 番石榴

Java 番石榴,java,guava,Java,Guava,我需要合并一些范围 我发现了番石榴,并看到它在某些情况下可以处理它 RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 10)); // {[1, 10]} rangeSet.add(Range.closed(8, 15)); // {[1, 15]} RangeSet RangeSet=TreeRangeSet.create(); rangeSet.add(Range.c

我需要合并一些范围

我发现了番石榴,并看到它在某些情况下可以处理它

RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closed(1, 10)); // {[1, 10]}
rangeSet.add(Range.closed(8, 15)); // {[1, 15]}
RangeSet RangeSet=TreeRangeSet.create();
rangeSet.add(Range.closed(1,10));//{[1, 10]}
rangeSet.add(Range.closed(8,15));//{[1, 15]}
现在,我需要告诉番石榴,我需要的是
[1,10]+[11,20]={[1,20]}
,而不是
{[1,10],[11,20]}


这有什么选择吗?

免责声明:我不熟悉番石榴

上述两个范围不合并的原因是10和11之间存在差距。要获得要组合的范围,您需要以下两种情况之一:

  • 第一个范围的结尾大于第二个范围的开头。(以上示例中就是这种情况)

  • 如果第一个和第二个范围的值相同,则必须将它们都视为“打开”。说明了如何区分打开和关闭范围


  • 如果要合并这样的范围,需要首先对其进行规范化:

    rangeSet.add(Range.closed(1, 10).canonical(DiscreteDomain.integers()); 
    // {[1, 11)}
    rangeSet.add(Range.closed(11, 20).canonical(DiscreteDomain.integers());
    // {[1, 21)}
    

    我认为
    TreeRangeSet
    实现有缺陷

    定义了以下合同:

    选择支持添加(范围)操作的实现需要忽略>空范围并合并连接的范围。例如:

    public void addRangeToSet(int lowerBound, int upperBound, RangeSet<Integer> set){
        set.add(Range.closedOpen(lowerBound, upperBound + 1));
    }
    
    ...
    
    addRangeToSet(1, 10, set); // {[1, 11)}
    addRangeToSet(11, 20, set); // {[1, 21)}
    
    rangeSet.add(Range.closedOpen(1, 10)); // {[1, 10)}
    rangeSet.add(Range.closedOpen(11, 20)); // {[1, 21)}
    
    有几种情况:

    • [1,10]+[11,15)
      没有合并,但它们是连接在一起的
    • [10,15)+(15,20)
      没有合并,这是正常的,因为它们是断开连接的。但是,javadoc代码段中的注释说它应该合并
    • [10,10]+[11,20)
      没有合并,但它们是连接在一起的
    我认为唯一的方法是添加“closedOpen”范围,将上限设置为实际上限+1,直到修复为止:

    您可以通过@LouisWasserman'的方式,或者:

    rangeSet.add(Range.closedOpen(1, 11)); // {[1, 11)}
    rangeSet.add(Range.closedOpen(11, 21)); // {[1, 21)}
    
    您还可以创建一个方法来“自动化”上限技巧,例如:

    public void addRangeToSet(int lowerBound, int upperBound, RangeSet<Integer> set){
        set.add(Range.closedOpen(lowerBound, upperBound + 1));
    }
    
    ...
    
    addRangeToSet(1, 10, set); // {[1, 11)}
    addRangeToSet(11, 20, set); // {[1, 21)}
    
    rangeSet.add(Range.closedOpen(1, 10)); // {[1, 10)}
    rangeSet.add(Range.closedOpen(11, 20)); // {[1, 21)}
    
    ImmutableRangeSet rangeSet=ImmutableRangeSet.builder()
    .add(范围.closed(1,10).canonical(离散域.integers())
    .添加(范围.关闭(11,15))
    .build()
    
    你能举个例子说明这一点吗?它与日期有关,但我想保持简单。如果你从1月1日工作到11日,从1月12日工作到20日,你实际上是从1日工作到20日。我需要在我的应用程序中将信息保存在一行中。这是按预期工作的。
    [1,10]
    [11,15)
    不被认为是由连接的。这在
    RangeSet
    文档中明确提到:“注意Range.isEmpty()和Range.isConnected(Range)的行为可能与离散范围上的预期不同。”我同意,你在我编辑我的答案时添加了你的评论,引用了isConnected doc;)但是,我仍然认为doc在
    [10,15](15,20)
    这件事上是错误的。
    public void addRangeToSet(int lowerBound, int upperBound, RangeSet<Integer> set){
        set.add(Range.closedOpen(lowerBound, upperBound + 1));
    }
    
    ...
    
    addRangeToSet(1, 10, set); // {[1, 11)}
    addRangeToSet(11, 20, set); // {[1, 21)}
    
    rangeSet.add(Range.closedOpen(1, 10)); // {[1, 10)}
    rangeSet.add(Range.closedOpen(11, 20)); // {[1, 21)}
    
    rangeSet.add(Range.closed(1, 10).canonical(DiscreteDomain.integers());  // {[1, 11)}
    rangeSet.add(Range.closed(11, 20).canonical(DiscreteDomain.integers()); // {[1, 21)}
    
    ImmutableRangeSet<Integer> rangeSet = ImmutableRangeSet.<Integer>builder()
            .add(Range.closed(1, 10).canonical(DiscreteDomain.integers()))
            .add(Range.closed(11, 15))
            .build()