Reputation:
Given the following method
public int calcSum(List<MyClass> items) {
return items.stream()
.mapToInt(i -> i.getHeight())
.sum();
}
what are my options for using different getters that I can pass in the method's arguments so that I don't have to repeat the same return statement with getWeight()
for example?
I was thinking of maybe using a different method that would return the getters (if that's possible) but I'm having trouble thinking of a good implementation for that. Thanks for the help!
Upvotes: 1
Views: 89
Reputation: 140484
Pass in a ToIntFunction<T>
as a parameter:
public <T> int calcSum(List<T> items, ToIntFunction<? super T> fn) {
return items.stream()
.mapToInt(fn)
.sum();
}
// Example invocations:
int heightSum = calcSum(items, MyClass::getHeight);
int weightSum = calcSum(items, MyClass::getWeight);
The <? super T>
is a a bounded wildcard (specifically a lower-bounded wildcard). It just makes the API a little bit more flexible. For example, because of the wildcard, you can call:
ToIntFunction<Object> constantValue = a -> 1;
int count = calcSum(items, constantValue);
Because constantValue
accepts any Object
, it can also accept MyClass
instances.
Without the bound, you would not be able to pass in a ToIntFunction<Object>
: for different list element types, you'd need to have separate instances:
ToIntFunction<MyClass> constantValueForMyClass = a -> 1;
ToIntFunction<MyOtherClass> constantValueForMyOtherClass = a -> 1;
ToIntFunction<YetAnotherClass> constantValueForYetAnotherClass = a -> 1;
// ...
which is just tedious and repetitive.
Upvotes: 8