如何使用自然顺序和比较器编写函数

时间:2018-01-19 08:40:20

标签: java code-reuse

我是Java新手,我正在尝试实现一种可以使用自然顺序或给定比较器参数的排序算法。

假设我有一个具有自然顺序C的比较类compareTo,比较器子类ByAltOrder,并且我有一个Comparator<C>方法,它返回一个新的{{1} }}

ByAltOrder

我想编写一个可以使用自然顺序或替代顺序的函数。我知道如何编写一个使用 自然顺序或替代顺序的函数,但我不想编写相同的代码两次,只是略有不同。这可能吗?

假设我想写一个返回非空数组最大值的函数。有了自然顺序,它看起来像这样:

public class C implements Comparable<C> {
        ...                                     //fields and constructor
    public int compareTo(C that) { ... }        //natural order
    public Comparator<C> altOrder() {           //some alternative order
        return new ByAltOrder();
    }
    public class ByAltOrder implements Comparator<C>{
        public int compare(C x, C y) { ... }
    }
}

使用Comparator,它看起来像这样,我可以传递public C max(C[] xs){ res = xs[0]; for (i = 1; i < xs.length; i++) { if (xs[i].compareTo(res) > 0) { res = points[i]; } } return res; } 作为第二个参数:

x.altOrder()

但是我怎么写一个包含两者的函数?

编辑:我得知Java中有public C max(C[] xs, Comparator c){ res = xs[0]; for (i = 1; i < xs.length; i++) { if (c.compare(xs[i], res) > 0) { res = points[i]; } } return res; } ,但实现sort或max只是我传递Comparators /代码重用/ java实践的问题的一个玩具示例。也许我没有说清楚这一点。

3 个答案:

答案 0 :(得分:4)

如果您真的想避免代码重复,则根本不应该实现该操作。

Comparator<C> altOrder = …;
C[] array = …;
C naturalMax = Collections.max(Arrays.asList(array));// natural order
C altMax     = Collections.max(Arrays.asList(array), altOrder); // alternative order

请注意Arrays.asList不会复制但只包装数组,因此没有性能考虑因素阻止使用这些方法。

顺便说一下,ByAltOrderaltOrder()都应该是static,因为它们不依赖于C的特定实例。

如果您想将这些方法作为练习实施,已经指出了其他答案,请使用委托和Comparator.naturalOrder()

如果您不使用Java 8或更新版本,则此内置比较器不可用,但您可以使用Collections.reverseOrder(Collections.reverseOrder())来解决它以获得具有相同行为的比较器,但是,当然,您应该更换只要迁移到Java 8或更高版本,就会Comparator.naturalOrder()

答案 1 :(得分:3)

技术上JB Nizet是对的。
这就足够了:

public C max(C[] xs){
    return max(xs, Comparator.naturalOrder());
}

public C max(C[] xs, Comparator<? super C> c){
    C res = xs[0];
    for (int i = 1; i < xs.length; i++) {
        if (c.compare(xs[i], res) > 0) {
            res = points[i];
        }
    }
    return res;
}

现在,具体而言,编写这些处理似乎并不相关 要查找数组的最大元素(以Comparable/Comparator表示),您只需使用Arrays.stream().max

C max = Arrays.stream(xs).max(c); 

C max =  Arrays.stream(xs).max(new ByAltOrder());

如果数组为空,则处理null大小写(感谢亲爱的Holger),您的方法可以简单如下:

public C findMax(C[] xs){
   return findMax(xs, Comparator.naturalOrder());
}

public C findMax(C[] xs, Comparator<? super C> c){
    return Arrays.stream(xs).max(c).orElse(null);
}

答案 2 :(得分:1)

你可以这样做:

public <C extends Comparable<? super C>> C max(C[] xs){
    return max(xs, Comparator.naturalOrder());
}

public <C> C max(C[] xs, Comparator<C> c){
    C res = xs[0];
    for (C x: xs) {
        if (c.compare(x, res) > 0) {
            res = x;
        }
    }
    return res;
}