【问题标题】:return method refference to stream返回流的方法引用
【发布时间】:2021-01-22 15:18:51
【问题描述】:

我有一堂课Care

class Car{
  private int wheels;
  private int doors;
 
  ...   

  public int getWheels(){ return wheels;}
  public int getDoors(){ return doors:}
}

我收藏了一些汽车

List<Car> cars = ...

我想计算集合中门窗的平均数量。我可以这样做:

cars.stream().mapToInt(Car::getWheels).avg().orElse(0.0)
cars.stream().mapToInt(Car::getDoors).avg().orElse(0.0)

但是,我想为此创建一个动态函数,例如:

public double calculateAvgOfProperty(List<Car> cars, String property){
  Function<Car,Integer> mapper = decideMapper(property);
  return cars.stream().maptoInt(mapper).avg().orElse(0.0);
}

public Function<Car,Integer> decideMapper(String ppr){
   if( ppr.equals("doors")  return Car::getDoors;
   if( ppr.equals("wheels") return Car::getWheels;
}

但是,.mapToInt() 需要ToIntFunction&lt;? super T&gt; mapper 作为参数,但方法引用是Function&lt;Car,Integer&gt;,并且强制转换不起作用。

但是,当我直接传递方法引用时,例如.mapToInt(Car::getDoors),它可以工作。

那么如何正确地将Function&lt;Car,Integer&gt; 转换为所需的类型?

【问题讨论】:

  • 只是猜测:您不能将方法签名中的返回类型更改为? extends Car(或类似的东西)吗?
  • 请注意:我不确定.avg()IntStream 实例上是否可用。

标签: java java-stream method-reference


【解决方案1】:

您不应将Function 转换为ToIntFunction,因为它们没有关联(ToIntFunction 不扩展Function)。然而它们都是函数式接口,所以方法引用也可以直接推断为ToIntFunction

IntStream 中定义了一个average() method

public double calculateAvgOfProperty(List<Car> cars, String property) {
    ToIntFunction<Car> mapper = decideMapper(property);
    return cars.stream().mapToInt(mapper).average().orElse(0.0);
}

public ToIntFunction<Car> decideMapper(String ppr){
     if( ppr.equals("doors"))  return Car::getDoors;
     if( ppr.equals("wheels")) return Car::getWheels;
     ...
}

【讨论】:

  • 当然,decideMapper 方法也需要为默认情况返回一些内容,或者(也许更好)抛出异常。 (我知道您为此添加了“...”,我只是想澄清那里省略的内容)
  • decideMapper 一开始也是有问题的,因为它没有以动态方式提取方法。
【解决方案2】:

你的意思是创建这样的方法吗:

private double calculateAvgOfProperty(List<Car> cars, Function<Car, Integer> function) {
    return cars.stream().mapToDouble(function::apply)
            .average()
            .orElse(0.0);
}

然后你只能调用:

double r1 = calculateAvgOfProperty(cars, Car::getWheels);
double r2 = calculateAvgOfProperty(cars, Car::getDoors);

我不太明白你的问题,但如果你愿意,可以将mapToDouble 替换为mapToInt

【讨论】:

    【解决方案3】:

    我不确定您要实现什么目标,但我敢肯定,您的代码中有很多编译时错误:

    1. decideMapper 方法中缺少一些右大括号;
    2. 默认情况下,您实际上并没有返回任何内容,来自decideMapper
    3. 在 IntStream 上调用一些 .avg(),这是不可用的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      • 1970-01-01
      • 2015-05-02
      • 1970-01-01
      • 2017-03-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多