【问题标题】:Using BiFunction in place of a Comparator does not work使用 BiFunction 代替 Comparator 不起作用
【发布时间】:2019-04-12 14:21:20
【问题描述】:

在初始化 TreeMapTreeSet 等集合时,我们可以添加自定义比较器。 代码如下所示:

Map<Integer, String> map1 = new TreeMap<>(new Comparator<Integer>() {
    public int compare(Integer x, Integer y) {
        return x-y;
    }
});

现在,我们可以用 lambda 表达式替换这个匿名实现。代码如下所示:

Map<Integer, String> map2 = new TreeMap<>((x,y) -> x-y);

Java-8 允许您通过functional interfaces 将 lambda 表达式存储在变量中。所以,我将上面的代码修改为:

BiFunction<Integer, Integer, Integer> myComparator = (x,y) -> x-y;
Map<Integer, String> map3 = new TreeMap<>(myComparator);

但是最后一次尝试没有成功!它给出了以下错误:

无法推断 TreeMap 的类型参数

为什么在上一个示例中解析类型失败?

注意:为了确认这不是 IDE 错误,我使用 javac 执行了原始编译,但仍然给出了相同的错误。

【问题讨论】:

  • 您不能将您的 lambda 函数声明为 Comparator&lt;Integer&gt; myComparator = (x,y) -&gt; x-y; 而不是 BiFunction 吗?因为Comparator 明确是TreeMap 构造函数需要的类型。
  • 我得到一个“无法解析构造函数....”.
  • @luk2302,你用的是哪个版本的java?
  • @khelwood 有效!!。但不幸的是并没有解决问题。
  • 无论你实现了哪种逻辑,都不要使用减号。 Integer.compare(int,int) 做正确的事,但通常,当您最终比较两个 int 值时,您可以使用 Comparator.naturalOrder()Comparator.reverseOrder​()Comparator.comparingInt​(…) 或它们的组合。

标签: java generics lambda java-8 functional-interface


【解决方案1】:

虽然 lambda 表达式看起来相同,但 BiFunction 不是 Comparator,因此您不能互换它们。

Comparator<Integer> comparator = (x,y) -> x - y;
Map<Integer, String> map3 = new TreeMap<>(comparator);

让我们深入了解这些接口并使用匿名类实现它们:

Comparator<Integer> comparator = new Comparator<Integer>() {
    @Override
    public int compare(Integer x, Integer y) {
        return x - y;
    }
};

BiFunction<Integer, Integer, Integer> biFun = new BiFunction<Integer, Integer, Integer>() {
    @Override
    public Integer apply(final Integer x, final Integer y) {
        return x - y;
    }
};

不同之处还在于方法的名称。 TreeMap 在其构造函数中需要 Comparator,因为它的内部实现将根据与 Comparator 的合同调用 compare

顺便说一下,BinaryOperator&lt;T&gt; 也会产生相同的 lambda 表达式。

【讨论】:

    【解决方案2】:

    这仅仅是因为TreeMap 构造函数需要Comparator&lt;Integer&gt; 而不是BiFunction

    BiFunction&lt;Integer, Integer, Integer&gt; myComparator = ... 你明确告诉编译器变量是那个类型的。这可以防止编译器推断TreeMap 构造函数所需的类型。由于BiFunction 不是Comparator,也不是它的子类,因此编译器不允许这样做。

    【讨论】:

      【解决方案3】:

      因为它需要 Comparator 并且您已经提供了 BiFunction。 来自 Oracle 文档:

      @FunctionalInterface
      public interface Comparator<T>
      

      一个比较函数,它对某些对象集合进行总排序。比较器可以传递给排序方法(例如 Collections.sort 或 Arrays.sort),以允许精确控制排序顺序。比较器还可用于控制某些数据结构(例如排序集或排序图)的顺序,或为不具有自然排序的对象集合提供排序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-26
        • 2011-02-21
        • 2017-03-26
        • 1970-01-01
        相关资源
        最近更新 更多