Search code examples
javajava-streamcollectors

Cannot figure out return type of Collectors.groupingBy


Similar issues have been answered before but I still wasn't able to figure out what is the problem with my grouping and averaging method.

I have tried multiple return value combinations like Map<Long, Double>, Map<Long, List<Double>, Map<Long, Map<Long, Double>>, Map<Long, Map<Long, List<Double>>> and none of those fix the error IntelliJ throws at me: 'Non-static method cannot be referenced from a static context'. At the moment I feel like I'm just blindly guessing. So could anyone perhaps give me some insight on how to determine the correct return type? Thanks!

Method:

public static <T> Map<Long, Double> findAverageInEpochGroup(List<Answer> values, ToIntFunction<? super T> fn) {
    return values.stream()
            .collect(Collectors.groupingBy(Answer::getCreation_date, Collectors.averagingInt(fn)));
}

Answer class:

@Getter
@Setter
@Builder
public class Answer {
    private int view_count;
    private int answer_count;
    private int score;
    private long creation_date;
}

Solution

  • The compiler error I get is different, about how the method call to collect is not applicable for the arguments.

    Your return type of Map<Long, Double> is correct, but what is going wrong is your ToIntFunction<? super T>. When you make this method generic, you are saying that the caller has control over T; a caller can supply a type argument, e.g.:

    yourInstance.<FooBar>findAverageInEpochGroupOrig(answers, Answer::getAnswer_count);
    

    However, this method doesn't need to be generic. Just take in a ToIntFunction<? super Answer> to operate on the Answer for the values of the map. This compiles:

    public static Map<Long, Double> findAverageInEpochGroup(List<Answer> values, ToIntFunction<? super Answer> fn) {
        return values.stream()
                .collect(Collectors.groupingBy(Answer::getCreation_date, Collectors.averagingInt(fn)));
    }
    

    As an aside, normal Java naming conventions specify that you would name your variable in camel case, e.g. "viewCount" instead of "view_count". This would affect any getter and setter methods as well.