Java 红黑树再平衡问题?

Java 红黑树再平衡问题?,java,collections,Java,Collections,compareTo方法对放入标准java树集合(即实现为红黑树的集合)的对象进行排序是否有任何约束?我有 公共类规则元组实现了可比较的{ 线头; 字符串[]rhs; 公共字符串toString(){ StringBuffer b=新的StringBuffer(); b、 追加(头+“:”); 用于(字符串t:rhs) b、 附加(“+t”); 返回b.toString(); } 公共整数比较(对象对象对象){ 规则元组src=(规则元组)obj; int cmp=头部比较(src头部); 如果(

compareTo方法对放入标准java树集合(即实现为红黑树的集合)的对象进行排序是否有任何约束?我有

公共类规则元组实现了可比较的{
线头;
字符串[]rhs;
公共字符串toString(){
StringBuffer b=新的StringBuffer();
b、 追加(头+“:”);
用于(字符串t:rhs)
b、 附加(“+t”);
返回b.toString();
}
公共整数比较(对象对象对象){
规则元组src=(规则元组)obj;
int cmp=头部比较(src头部);
如果(cmp!=0)
返回cmp;
if(rhs.length!=src.rhs.length)
返回rhs.length-src.rhs.length;
对于(int i=0;i,比较器和可比性的另一个(通常被忽略的)条件是“临时一致性”,即,两个对象的比较结果不应改变,只要它们被用作树映射中的键(或使用Comparator/Comparable的任何其他结构,如用于Collections.binarySearch的排序数组,或由最小堆实现的PriorityQueue-即使对于array.sort-在排序完成之前,不应更改元素)

这本质上意味着您的键不应更改,至少不应以顺序更改的方式更改

原因是树映射假定二叉树的节点总是按正确的顺序排列-正因为如此,它可以在
O(log(n))
中工作,而不是在
O(n)
中进行查找和更改

如果必须更改密钥,应首先将其从结构中删除,然后更改,然后再次添加

(顺便说一句,对于HashMap等基于哈希的结构中的键的
equals
hashCode
也是如此。)


作为额外的奖励,这里有一个使用代码变体的泛型:

public class RuleTuple implements Comparable<RuleTuple> {
    String head;
    String[] rhs;
    public String toString() {
        StringBuilder b = new StringBuilder();
        b.append(head+":"); 
        for( String t: rhs ) 
           b.append(" "+t); 
        return b.toString();
    }
    public int compareTo(RuleTuple src) {
        int cmp = head.compareTo(src.head);
        if( cmp!=0 )
            return cmp;
        if( rhs.length != src.rhs.length )
            return rhs.length - src.rhs.length;
        for( int i=0; i<rhs.length; i++ ) {
            int diff = rhs[i].compareTo(src.rhs[i]);
            if(diff != 0)
                return diff;
        }
        return 0;
    }
    ...
}
公共类规则元组实现了可比较的{
线头;
字符串[]rhs;
公共字符串toString(){
StringBuilder b=新的StringBuilder();
b、 追加(头+“:”);
用于(字符串t:rhs)
b、 附加(“+t”);
返回b.toString();
}
公共整数比较(规则元组src){
int cmp=头部比较(src头部);
如果(cmp!=0)
返回cmp;
if(rhs.length!=src.rhs.length)
返回rhs.length-src.rhs.length;

对于(int i=0;i另一个条件是“临时一致性”,即比较两个对象的结果不应改变,只要它们在树映射中用作键。这意味着您的键本质上不应改变。这可能是键(双关语)!i do transform(替换规则)在原地.Argh,走捷径时总是有问题…当
this.head==null
但是
src.head!=null
时会发生什么?我想在切换视点时会出现NullPointerException。另外,您可能会考虑不调用
rhs[I].compareTo(src.rhs[I])
两次。(这只是一个优化,不是问题的原因,我真的不明白。)除此之外(你应该在这里使用泛型),您的compareTo方法看起来很好。为了避免一致性问题:从集合/映射中删除规则,对其进行更改,然后再次添加。我编辑了这篇文章,因为空问题与此无关。按照Paulo的建议修复了变异问题后,代码似乎运行良好。这是问题注释中讨论的要点。我碰巧遇到了rand我第一句话就说到了解决办法。
test[22,33): 'HAVING' condition               <-- comparison#1
   test: test[4,19) group_by_clause           <-- comparison#2
       test: model_clause                     <-- comparison#3
           test: group_by_clause
              test:
              test: test[22,33)
           test: group_by_clause test[22,33)  <-- comparison#4; wrong branch!
              test: test[4,19)                <-- comparison#5
              test: group_by_clause model_clause
                  ...
       test: test[4,19) group_by_clause model_clause
        ...
   test[4,19): test[5,8) test[8,11)
        ...
public class RuleTuple implements Comparable<RuleTuple> {
    String head;
    String[] rhs;
    public String toString() {
        StringBuilder b = new StringBuilder();
        b.append(head+":"); 
        for( String t: rhs ) 
           b.append(" "+t); 
        return b.toString();
    }
    public int compareTo(RuleTuple src) {
        int cmp = head.compareTo(src.head);
        if( cmp!=0 )
            return cmp;
        if( rhs.length != src.rhs.length )
            return rhs.length - src.rhs.length;
        for( int i=0; i<rhs.length; i++ ) {
            int diff = rhs[i].compareTo(src.rhs[i]);
            if(diff != 0)
                return diff;
        }
        return 0;
    }
    ...
}