基本上,我有一个通用BST,我想为Comparable
对象和对象使用关联的Comparator
类。例如,我希望该树可以与Integers
一起使用,也可以用于Point2D
,其中点可以按X方向或Y方向排序(为此我有相应的比较器)。我想知道做这个的标准方法是什么?我想出了这个:适用于可比较和比较器的泛型
public class Test <Data> {
public <Data extends Comparable> Test() {
System.out.println("Comparable");
this.c = null;
}
public Test(Comparator<Data> comparator) {
System.out.println("Comparator");
this.c = comparator;
}
public int compare(Data d1, Data d2) {
if (c == null) {
return ((Comparable)d1).compareTo(d2);
} else {
return this.c.compare(d1,d2);
}
}
Comparator<Data> c;
public static void main(String[] args) {
Test<Integer> test = new Test<Integer>();
System.out.println(test.compare(1,2));
Test<Point2D> test2 = new Test<Point2D>(Point2DCompare.Comparators.X);
System.out.println(test2.compare(new Point2D.Double(1,2),new Point2D.Double(2,2)));
}
}
其中Point2DCompare.Comparators.X
是,通过他们的X坐标点排序一个简单的比较。这似乎工作,但它有点难看。我想知道是否有标准的方法来解决这个问题?
编辑:实现基于user1676075:
public class Test <Data> {
public <Data extends Comparable> Test() {
dataComparator = new Comparator<Data>() {
@Override
public int compare(Data p1,Data p2) {
return p1.compareTo(p2);
}
};
}
public Test(Comparator<Data> comparator) {
dataComparator = comparator;
}
public final Comparator dataComparator;
public static void main(String[] args) {
Test<Integer> test = new Test<Integer>();
System.out.println(test.dataComparator.compare(1,2));
Test<Point2D> test2 = new Test<Point2D>(Point2DCompare.Comparators.X);
System.out.println(test2.dataComparator.compare(new Point2D.Double(1,2),new Point2D.Double(2,2)));
}
}
EDIT2:与第二个实施的一个问题是,它并不会导致编译错误,如果没有使用非可比Data
比较。例如:
Test<Point2D> test3 = new Test<Point2D>();
System.out.println(test3.dataComparator.compare(new Point2D.Double(1,2),new Point2D.Double(2,2)));
导致运行时错误。如果有一个完整的解决方案,这将是很好的。
另一种选择很可能会创建一个调用的compareTo(),如果你没有通过一个比较器,但我不确定这会是更清洁还是更高效。你有什么看起来不错。 – Tim 2014-09-23 19:55:15
@Tim我想我会坚持下去,直到更优雅的东西出现。 – Justin 2014-09-23 20:16:13
第二个是非常错误的。泛型构造函数创建一个* new *泛型类型参数'Data',它独立于类,并隐藏类中的类型参数'Data'。因此,例如,您可以将“Data”重命名为“Data2”。它也是不安全的,因为创建的比较器将是'Comparator',其中'Data2'是构造函数自己的'Data',它可以是任何东西(因为构造函数的签名在任何参数中都不使用'Data2')。而不是班级的“数据”。但是,变量'dataComparator'必须是'比较器','Data'是类的'Data'。 –
newacct
2014-09-23 23:01:23