Search code examples
javajava-streamcollectorsreducing

Java-Stream Collectors.reducing - cannot infer type-variable(s) T


This is my Employee class:

@AllArgsConstructor
@Getter
public static class Employee {
    public enum Gender {
        MALE, FEMALE
    }

    private long id;
    private String name;
    private Gender gender;
    private LocalDate dob;
    private double income;

    public static List<Employee> persons() {
        Employee p1 = new Employee(1, "Jake", Gender.MALE, LocalDate.of(1971,
            Month.JANUARY, 1), 2343.0);
        Employee p2 = new Employee(2, "Jack", Gender.MALE, LocalDate.of(1972,
            Month.JULY, 21), 7100.0);
        Employee p3 = new Employee(3, "Jane", Gender.FEMALE, LocalDate.of(1973,
            Month.MAY, 29), 5455.0);
        Employee p4 = new Employee(4, "Jode", Gender.MALE, LocalDate.of(1974,
            Month.OCTOBER, 16), 1800.0);
        Employee p5 = new Employee(5, "Jeny", Gender.FEMALE, LocalDate.of(1975,
            Month.DECEMBER, 13), 1234.0);
        Employee p6 = new Employee(6, "Jason", Gender.MALE, LocalDate.of(1976,
            Month.JUNE, 9), 3211.0);
    
        List<Employee> persons = Arrays.asList(p1, p2, p3, p4, p5, p6);
    
        return persons;
    }
}
    

I want to calculate the total income per gender.

My code:

Map<Gender, Double> totalIncomeByGender = Employee.persons().stream()
    .collect(Collectors.groupingBy(
        Employee::getGender, 
        Collectors.reducing(0,Employee::getIncome,Double::sum)));

I'm getting a compilation error:

java: no suitable method found for reducing(int,Employee::getIncome,Double::sum)
    method java.util.stream.Collectors.<T>reducing(T,java.util.function.BinaryOperator<T>) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ in length))
    method java.util.stream.Collectors.<T>reducing(java.util.function.BinaryOperator<T>) is not applicable
      (cannot infer type-variable(s) T
        (actual and formal argument lists differ in length))
    method java.util.stream.Collectors.<T,U>reducing(U,java.util.function.Function<? super T,? extends U>,java.util.function.BinaryOperator<U>) is not applicable
      (inference variable U has incompatible bounds
        lower bounds: java.lang.Double,java.lang.Object
        lower bounds: java.lang.Double,java.lang.Integer)

Can somebody please explain the reason of this error, and what is a correct way to write this code?

I've written a similar stream in a different code, and it worked. How can I fix it?


Solution

  • You've provided an identity of an incorrect type - Integer, because numeric literal 0 is of type int.

    Meanwhile, the result of reduction should be of type Double. That results in the type mismatch in the classifier function, since it gives a Double as required according to the resulting type of the map.

    To fix the compilation error, you need to change the identity to 0d or 0D.

    Map<Employee.Gender,Double> totalIncomeByGender = Employee.persons().stream()
        .collect(Collectors.groupingBy(
            Employee::getGender,
            Collectors.reducing(0D, Employee::getIncome,Double::sum)
        ));