适用于可比较和比较的通用

时间:2014-09-23 19:25:41

标签: java generics comparator comparable

基本上,我有一个通用的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)));

导致运行时错误。如果有完整的解决方案,那就太好了。

2 个答案:

答案 0 :(得分:1)

唯一类型安全的方法是使用静态工厂方法,根据类似的自然顺序而不是构造函数创建类。静态方法将是通用的,并且只接受满足可比自身约束的类型:

public class Test<Data> {
    Comparator<Data> c;

    public Test(Comparator<Data> comparator) {
        System.out.println("Comparator");
        this.c = comparator;
    }

    public static <T extends Comparable<? super T>> Test<T> createWithComparable() {
        System.out.println("Comparable");
        return new Test<T>(new Comparator<T>() {
            @Override
            public int compare(T p1,T p2) {
                return p1.compareTo(p2);
            }
        });
    }
}

答案 1 :(得分:0)

创建默认比较器。默认比较器的行为是查看并查看这两个对象是否为Comparable。如果是这样比较它们,如果没有,则抛出异常。将此比较器分配给类中的实例变量。

然后你有两个选择。使用可选的Comparator创建类(在这种情况下,您替换默认的比较器),比较代码只使用分配给该实例变量的比较器,或者您的比较方法可选择使用比较器并使用传入的比较器或您的比较器默认如果没有传递。使用这些方法中的哪一种取决于您的课程如何被调用。