【问题标题】:How can I pass a comparison function into a Java method?如何将比较函数传递给 Java 方法?
【发布时间】:2019-05-03 20:32:53
【问题描述】:

我正在将一些代码从 Python 移植到 Java 8,但我坚持使用一种方法,其中一个参数是矩阵,另一个是比较函数,在 Python 中类似于 np.gtnp.lt

我发现这很难在 Java 中实现,因为 Java 比较(比较器)只对复杂类型进行操作,而自动装箱似乎不起作用。

我想写的是:

public static boolean[][] matrix_check(double[][] matrix, Comparator<double> comparator) {
    // ...
}

但是Comparator&lt;double&gt; 显然不起作用。我应该如何在 Java 中实现这个功能?

【问题讨论】:

  • 使用Comparator&lt;Double&gt;
  • “这个功能”到底是什么?您要在结果中设置的布尔值是什么?

标签: java lambda java-8 functional-programming comparator


【解决方案1】:

使用Comparator 作为形式参数之一的定义方法意味着您可以在其中传递与Comparator 对应的功能接口的lambda 表达式。不要忘记将 Comparator 包裹在盒装类型周围,因为您不能使用原始类型。

关键是Comparator::compare,它返回int,因此行为类似于BiFunction&lt;T, T, Integer&gt;,应缩短为lambda表达式(或在某些情况下为方法引用):

double[][] doubleArray = ...
Comparator<Double> comparator = (left, right) -> (int)(left - right);  
boolean[][] booleanArray = matrix_check(doubleArray, comparator);

也可以直接传递 lambda 表达式:

double[][] newDoubleArray = matrix_check(doubleArray, (int)(left - right));

在上面的示例中,您必须注意转换为 int 时会损失的精度。 doubles 不适用于 lambda 表达式解释。对于实现Comparable 的整数或对象,整个事情会容易得多:

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 

【讨论】:

  • (left, right) -&gt; left - rightComparator&lt;Double&gt; 不兼容:left - right 的类型为 double,而不是 int
  • @AndyTurner:感谢您的留言,我去修复它:)
  • 更好的比较是Double.compare(left,right) 或简单的Double::compare
  • 我不明白为什么这个“减法等于比较”的神话如此顽固。 a) 当您使用(l, r) -&gt; l- r 比较整数时,lr 之间的距离可能大于int 值空间并导致溢出。 b) 当您使用(left, right) -&gt; (int)(left - right) 比较浮点值时,距离可能小于一并四舍五入为零。肯定不是你想要的,也违反了传递性约束:比较0.51.0 产生零,比较1.01.5 产生零,但比较0.51.5 产生非零→坏。
  • @Naman 使用 Double.compare 不仅更好,而是使用减号完全被破坏。
【解决方案2】:

Java 泛型不支持原始类型。 您需要通过 Comparator&lt;Double&gt; 代替。 您可以将doubleDouble 值与这样的比较器进行比较。比较 double 值将利用自动装箱。

【讨论】:

    【解决方案3】:

    我最终使用了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; };
    

    其他二元运算很容易添加。

    方法定义和比较器用法如下:

    public static Boolean[][] matrix_check(double[][] matrix, DoubleBinaryOperator comparator) {
      if (comparator.applyAsDouble(arg1, arg2) > 0) {
        // Logic if true.
      } else {
        // Logic if false.
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多