【问题标题】:Seeking in-depth understanding of Function<T,R>寻求对Function<T,R>的深入理解
【发布时间】:2019-10-19 23:23:50
【问题描述】:

下面显示的是一些使用 Java Streams 的示例代码。我的问题特别与Interface Function&lt;T,R&gt; 相关,它接受T 类型的输入并返回R 类型的内容。

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.groupingBy;

import java.util.List;
import java.util.Map;

public class Dish {

  private final String name;
  private final boolean vegetarian;
  private final String calories;

  public Dish(String name, boolean vegetarian, String calories) {
    this.name = name;
    this.vegetarian = vegetarian;
    this.calories = calories;
  }

  public String getName() {
    return name;
  }

  public boolean isVegetarian() {
    return vegetarian;
  }

  public String getCalories() {
    return calories;
  }

  @Override
  public String toString() {
    return name;
  }

  public static final List<Dish> menu = asList(
      new Dish("pork", false, "GE 600"),
      new Dish("beef", false, "GE 600"),
      new Dish("chicken", false, "300-600"),
      new Dish("french fries", true, "300-600"),
      new Dish("rice", true, "LE 300"),
      new Dish("season fruit", true, "LE 300"),
      new Dish("pizza", true, "300-600"),
      new Dish("prawns", false, "300-600"),
      new Dish("salmon", false, "300-600")
  );

  public static void main(String[] args) {
        Map<String, List<Dish>> dishByCalories = menu.stream()
                .collect(groupingBy(Dish::getCalories));
        System.out.println(dishByCalories);
  }
}

显然groupingBy(Dish::getCalories) 满足collect 的预期方法签名要求(即Collector&lt;? super T,A,R&gt; collector

现在来到groupingsBy,它的签名要求如下:
static &lt;T,K&gt; Collector&lt;T,?,Map&lt;K,List&lt;T&gt;&gt;&gt; groupingBy(Function&lt;? super T,? extends K&gt; classifier)

我们传递给groupingsBy 的方法引用是Dish::getCalories

显然Dish::getCalories 满足Function&lt;? super T,? extends K&gt; 的签名要求(即它应该接受T 的某个超类的输入并返回K 的某个子类的结果)。

但是,getCalories 方法不接受任何参数,它返回一个字符串。

请帮助消除我的困惑。

【问题讨论】:

    标签: java functional-interface functional-java


    【解决方案1】:

    getCalories 是一个 instance 方法,因此它接受隐含的 this 参数。

    Dish::getCalories 等价于 lambda (Dish dish) -&gt; dish.getCalories(),这使其成为 Function&lt;Dish, String&gt; 的实现。

    【讨论】: