user11125276
user11125276

Reputation:

Using different getters in a method

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

Answers (1)

Andy Turner
Andy Turner

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

Related Questions