Reputation: 1316
I have a class Care
class Car{
private int wheels;
private int doors;
...
public int getWheels(){ return wheels;}
public int getDoors(){ return doors:}
}
And I have a collection of the cars
List<Car> cars = ...
I want to calculate the average numbers of doors and windows in the collection. I could do this:
cars.stream().mapToInt(Car::getWheels).avg().orElse(0.0)
cars.stream().mapToInt(Car::getDoors).avg().orElse(0.0)
However, I want to create a dynamic function for this, for example:
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;
}
However, .mapToInt()
requires ToIntFunction<? super T> mapper
as argument, but the method reference is Function<Car,Integer>
, and casting does not work.
However when I directly pass the method reference, for example .mapToInt(Car::getDoors)
, it works.
How to cast correctly cast Function<Car,Integer>
to required type then?
Upvotes: 0
Views: 99
Reputation: 11130
I'm not sure what you're trying to achieve, but I'm sure, that you have quite a few compile time errors in your code:
decideMapper
method;decideMapper
;.avg()
on IntStream, which is not available.Upvotes: 1
Reputation: 72874
You should not cast a Function
to a ToIntFunction
as they are not associated (ToIntFunction
does not extend Function
). They are however both functional interfaces, so the method reference can also be inferred directly as a ToIntFunction
.
There is an average()
method defined in IntStream
:
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;
...
}
Upvotes: 3
Reputation: 60036
Do you mean to create a method like this:
private double calculateAvgOfProperty(List<Car> cars, Function<Car, Integer> function) {
return cars.stream().mapToDouble(function::apply)
.average()
.orElse(0.0);
}
and then you can only call:
double r1 = calculateAvgOfProperty(cars, Car::getWheels);
double r2 = calculateAvgOfProperty(cars, Car::getDoors);
I don't understand very well your question, but you can replace mapToDouble
with mapToInt
if you want.
Upvotes: 2