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