Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java streams with generics

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)

like image 774
yaseco Avatar asked Apr 01 '19 07:04

yaseco


1 Answers

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}
like image 114
Eran Avatar answered Sep 27 '22 22:09

Eran