简体   繁体   中英

How to write a function using natural order and comparators

I am new to Java, and I am trying to implement a sort algorithm which may use the natural order or a given comparator argument.

Say I have a comparable class C with some natural order compareTo , a Comparator subclass ByAltOrder , And I have a Comparator<C> method which returns a new 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) { ... }
    }
}

I want to write a function which may use the natural order or the alternative order. I know how to write a function that uses either the natural order or the alternative order, but I do not want to write the same code twice with minor differences. Is that possible?

Say I want to write a function returning maximum of a non-empty Array. With natural order it looks like this:

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;
}

And with Comparator it looks like this and I can pass x.altOrder() as the second argument:

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;
}

But how I do write a function that incorporates both?

Edit: I got that there is an Arrays.sort in Java, but implementing sort or max is just a toy example for my question about passing Comparators / code reuse / java practice. Perhaps I didn't make it clear about this.

If you truly want to avoid code duplication, you should not implement that operation at all.

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

Note that Arrays.asList does not copy but only wraps the array, so there is no performance consideration preventing to use these methods.

By the way, ByAltOrder and altOrder() should both be static , as they don't depend on a specific instance of C .

If you want to implement these methods as an exercise, other answers already pointed to it, use delegation and Comparator.naturalOrder() .

If you are not using Java 8 or newer, this builtin comparator is not available, but you could work-around it using Collections.reverseOrder(Collections.reverseOrder()) to get a comparator with the same behavior, but, of course, you should replace that with Comparator.naturalOrder() as soon as you migrate to Java 8 or newer.

Technically JB Nizet is right.
This is enough :

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;
}

Now, concretely, writing these processings seem not relevant
To find the max element (in terms of Comparable/Comparator ) of an array, you could just use Arrays.stream().max :

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

or

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

By handling the null case if the array is empty (thanks dear Holger), your methods could be as simple as :

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);
}

You could do something like this:

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM