Reputation: 2570
I have a generic function which accepts Collection<? extends T> ts
.
I'm also passing:
Function<? extends T, ? extends K> classifier
which maps each item T
to a key K
(possible to have duplicates)
Function<? extends T, Integer> evaluator
which gives an integer value for the item.
The function itself has a built-in calculation ("int to int
") for every produced Integer
(could be something like squaring for our example)
Finally, I'd like to sum all of the values for each key.
So the end result is: Map<K, Integer>
.
For example,
Let's say we have the list ["a","a", "bb"]
and we use Function.identity
to classify, String::length
to evaluate and squaring as the built-in function. Then the returned map will be: {"a": 2, "b": 4}
How can I do that? (I guess that preferably using Collectors.groupingBy
)
Upvotes: 5
Views: 1587
Reputation: 120848
Or another approach:
private static <K, T> Map<K, Integer> map(Collection<? extends T> ts,
Function<? super T, ? extends K> classifier,
Function<? super T, Integer> evaluator,
Function<Integer, Integer> andThen) {
return ts.stream()
.collect(Collectors.groupingBy(
classifier,
Collectors.mapping(evaluator.andThen(andThen),
Collectors.reducing(0, Integer::sum))
));
}
And use it with:
public static void main(String[] args) {
System.out.println(map(
Arrays.asList("a", "a", "bb"),
Function.identity(),
String::length,
x -> x * x));
}
Upvotes: 2
Reputation: 393771
Here's one way to do it:
public static <T,K> Map<K,Integer> mapper (
Collection<T> ts,
Function<T, K> classifier,
Function<T, Integer> evaluator,
Function<Integer,Integer> calculator)
{
return
ts.stream()
.collect(Collectors.groupingBy(classifier,
Collectors.summingInt(t->evaluator.andThen(calculator).apply(t))));
}
The output for:
System.out.println (mapper(Arrays.asList("a","a","bb"),Function.identity(),String::length,i->i*i));
is
{bb=4, a=2}
Upvotes: 4