Reputation: 931
I'm porting some code from Python to Java 8 and am stuck on a method where one of the parameters is a matrix and the others is a comparison function, which in Python is something like np.gt
or np.lt
.
I'm finding this difficult to implement in Java, as Java comparisons (Comparator) only operate on complex types, and autoboxing doesn't seem to work.
What I'd like to write is:
public static boolean[][] matrix_check(double[][] matrix, Comparator<double> comparator) {
// ...
}
But Comparator<double>
obviously doesn't work. How should I implement this functionality in Java?
Upvotes: 1
Views: 2635
Reputation: 931
I ended up using DoubleBinaryOperator
.
DoubleBinaryOperator lt = (x, y) -> { if (x > y) return 1; else return -1; };
DoubleBinaryOperator gt = (x, y) -> { if (x < y) return 1; else return -1; };
Other binary operations are easily added.
Method definition and comparator usage then looks like:
public static Boolean[][] matrix_check(double[][] matrix, DoubleBinaryOperator comparator) {
if (comparator.applyAsDouble(arg1, arg2) > 0) {
// Logic if true.
} else {
// Logic if false.
}
Upvotes: 1
Reputation: 44496
Having the defined method with Comparator
as one of the formal parameters means that you can pass a lambda expression in it of a functional interface corresponding to Comparator
. Don't forget to wrap the Comparator
around the boxed types, since you cannot use the primitive ones.
The crucial is Comparator::compare
which returns int
and therefore behaves like a BiFunction<T, T, Integer>
, shall be shortened as a lambda expression (or a method reference in some cases):
double[][] doubleArray = ...
Comparator<Double> comparator = (left, right) -> (int)(left - right);
boolean[][] booleanArray = matrix_check(doubleArray, comparator);
The lambda expression might be passed directly as well:
double[][] newDoubleArray = matrix_check(doubleArray, (int)(left - right));
In the example above, you have to mind the precision lost with casting to int
. The double
s are not suitable for the lambda expression explanation. For integers or objects implementing Comparable
the whole thing would be much easier:
Comparator<Integer> c1 = (l, r) -> l- r; // l - r results in int
Comparator<String> c2 = (l, r) -> l.compareTo(r); // implements Comparable by default
Comparator<MyObject> c3 = (l, r) -> l.compareTo(r); // must implement Comparable
Upvotes: 4
Reputation: 26094
Java generics don’t support primitive types.
You need to pass Comparator<Double>
instead.
You can compare both double
and Double
values with such a comparator. Comparing double
values will leverage auto-boxing.
Upvotes: 3