使用泛型在java中实现B树

使用泛型在java中实现B树,java,generics,b-tree,Java,Generics,B Tree,我已经用java编写了自己的2-3-4树。目前,我的代码如下所示: public class tree234{ private class node{ Comparable data[]=new Comparable[3]; node next[]=new node[4]; } } public class tree234<T extends Comparable<? super T>>{

我已经用java编写了自己的2-3-4树。目前,我的代码如下所示:

public class tree234{  
    private class node{  
        Comparable data[]=new Comparable[3];  
        node next[]=new node[4];  
    }   
}
public class tree234<T extends Comparable<? super T>>{  
    private class node{  
        T[] data=new T[3];//error here!  
        node[] next=new node[4];  
    }  
}
相反,我想要这样的东西:

public class tree234{  
    private class node{  
        Comparable data[]=new Comparable[3];  
        node next[]=new node[4];  
    }   
}
public class tree234<T extends Comparable<? super T>>{  
    private class node{  
        T[] data=new T[3];//error here!  
        node[] next=new node[4];  
    }  
}

虽然我知道我不能创建数组,也不知道为什么,但我想不出一个合理简单的方法来用泛型实现node类。有什么建议吗?

您可以随时进行显式播放

由于T扩展了Comparable,因此变量T[]将在编译类中作为Comparable[]结束。因此数组类型必须是可比较的[]-不能将对象分配给可比较的变量

另一种数组类型是Tree234.Node[]


您始终可以执行显式强制转换

由于T扩展了Comparable,因此变量T[]将在编译类中作为Comparable[]结束。因此数组类型必须是可比较的[]-不能将对象分配给可比较的变量

另一种数组类型是Tree234.Node[]


啊,Java数组和泛型,我多么讨厌你。 虽然使用列表肯定可以解决键入问题,但有时数组的速度确实是必要的

反射当然是一种方法,在这里搜索更多,但我发现代码太臭了,不合我的口味。对于更简单的情况,您可以使用类似我下面介绍的ArrayConstructor接口。如果不是因为节点类型,我们可以在不发出任何警告的情况下解决您的问题,但代价是增加了代码的冗余度和泄漏的抽象,您的类的用户将不得不提供节点和T数组构造函数。不幸的是,由于节点类型也采用类型参数,因此我们无法在没有警告的情况下一般地处理这种情况

interface ArrayConstructor<T> {
  T[] constructArray(int size);
}

class Node <T extends Comparable<? super T>>{  
    private T[] data;
    private Node[] next;

    Node(ArrayConstructor<T> dataConstructor,
         ArrayConstructor<Node<T>> nodeConstructor){
        this.data = dataConstructor.constructArray(3);
        this.next = nodeConstructor.constructArray(4);
    }
}  

啊,Java数组和泛型,我多么讨厌你。 虽然使用列表肯定可以解决键入问题,但有时数组的速度确实是必要的

反射当然是一种方法,在这里搜索更多,但我发现代码太臭了,不合我的口味。对于更简单的情况,您可以使用类似我下面介绍的ArrayConstructor接口。如果不是因为节点类型,我们可以在不发出任何警告的情况下解决您的问题,但代价是增加了代码的冗余度和泄漏的抽象,您的类的用户将不得不提供节点和T数组构造函数。不幸的是,由于节点类型也采用类型参数,因此我们无法在没有警告的情况下一般地处理这种情况

interface ArrayConstructor<T> {
  T[] constructArray(int size);
}

class Node <T extends Comparable<? super T>>{  
    private T[] data;
    private Node[] next;

    Node(ArrayConstructor<T> dataConstructor,
         ArrayConstructor<Node<T>> nodeConstructor){
        this.data = dataConstructor.constructArray(3);
        this.next = nodeConstructor.constructArray(4);
    }
}  

除了显而易见的方法外,只需使用对象数组并强制转换返回值,还可以使用array.newInstanceclass、size并将返回值强制转换为T[]。您仍然必须抑制警告,因为当前泛型实现无法避免这种情况,但这种方式可以在将对象插入数组时进行类型检查,而不是在访问对象时进行类型检查,并且更早的错误会更好


在背景中使用反射,因此可能不是世界上性能最好的东西。

除了显而易见的问题,只需使用对象数组并强制转换返回值,您还可以使用array.newInstanceclass,size并将返回值强制转换为T[]。您仍然必须抑制警告,因为当前泛型实现无法避免这种情况,但这种方式可以在将对象插入数组时进行类型检查,而不是在访问对象时进行类型检查,并且更早的错误会更好

在背景中使用反射,因此可能不是世界上性能最好的东西。

您应该创建一个新的可比较的[4]。因为我相信这个数组是您的结构内部的,所以没有人真正关心数组的真正类型

然后,您可以1将其分配给T[]变量(如果您希望确保没有任何外部代码访问它),否则它将崩溃,或者2在取出元素时手动将其强制转换为T。无论哪种方式,您都会收到警告。

您应该创建一个新的可比较的[4]。因为我相信这个数组是您的结构内部的,所以没有人真正关心数组的真正类型

interface ArrayConstructor<T> {
  T[] constructArray(int size);
}

class Node <T extends Comparable<? super T>>{  
    private T[] data;
    private Node[] next;

    Node(ArrayConstructor<T> dataConstructor,
         ArrayConstructor<Node<T>> nodeConstructor){
        this.data = dataConstructor.constructArray(3);
        this.next = nodeConstructor.constructArray(4);
    }
}  

然后,您可以1将其分配给T[]变量(如果您希望确保没有任何外部代码访问它),否则它将崩溃,或者2在取出元素时手动将其强制转换为T。无论哪种方式,您都会收到警告。

您可以使用列表而不是数组吗?@Paul我的代码已经可以使用数组了,更改它会很烦人。不过,如果这是最好的方法,那也是可行的。看看这个问题,你能用列表代替数组吗?@Paul我的代码已经可以处理数组了,修改它会很烦人。但是,如果这是最好的方法,那么它是可行的。检查这个问题我已经尝试过了,但是得到了一个警告,并且不确定该方法是否安全。另外,当我运行一个测试程序时也发生了这种情况:线程主java.lang.ClassCastException中的异常:[Ljava.lang.Object;无法强制转换到[Ljava.lang.Comparable;好的,我修正了两种数组类型都使用裸的非泛型类型,因此不会发生类强制转换异常。我使用eclipse进行测试,没有发现异常
interface ArrayConstructor<T> {
  T[] constructArray(int size);
}

class Node <T extends Comparable<? super T>>{  
    private T[] data;
    private Node[] next;

    Node(ArrayConstructor<T> dataConstructor,
         ArrayConstructor<Node<T>> nodeConstructor){
        this.data = dataConstructor.constructArray(3);
        this.next = nodeConstructor.constructArray(4);
    }
}  

警告。如果你得到“未检查”的警告,这些警告可以被忽略或禁止-@suppressWarningunchecked,因为这是安全的。我相信运行时版本和非通用版本一样快,但我没有费心检查字节码…欢迎你。请随意勾选“接受答案”复选框……我已经尝试过了,但得到了一个警告,不确定该方法是否安全。此外,当我运行测试程序时也发生了这种情况:线程主java.lang.ClassCastException中的Exception:[Ljava.lang.Object;无法转换为[Ljava.lang.Comparable;好的,我修正了两种数组类型都使用裸非泛型类型,因此不会发生类强制转换异常。我使用eclipse进行测试,没有收到任何警告。如果您收到“未检查”警告,则可以忽略或禁止这些警告-@suppressWarningUnchecked,因为这是安全的。我相信运行时版本与n一样快在通用版本上,但我没有费心检查字节码…不客气。请随意勾选接受答案复选框…我建议使用新的可比[4],这样在比较键时就不必强制转换。我建议使用新的可比[4],这样在比较键时就不必强制转换。