Emdee
Emdee

Reputation: 1693

Non-static method cannot be referenced from a static context inside Collectors.toMap

I have a list of Students which I want to convert into a Map<String, Integer>, where the map key should be the first name of the student. To keep the code sample simple, I specified the map value as 1:

final Map<String, Integer> map = someStudents.stream().collect(
        Collectors.toMap(Student::getFirstName, 1));

The compiler complains about:

non-static method getFirstName() cannot be referenced from a static context

Any idea? I am confused because many examples use the same approach of passing a reference to the non-static method. Why does the compiler see a static context here?

Upvotes: 12

Views: 16476

Answers (3)

ACV
ACV

Reputation: 10560

The issue here is that first of all, this message is very misleading and that seems to be a java bug. Second, you are providing an int value in place of a function reference. Correct is this:

final Map<String, Integer> map = someStudents.stream().collect(
        Collectors.toMap(Student::getFirstName, val -> 1));

Here val -> 1 is a function which for any val will always return 1.

Another situation where you would get the same error would be this:

 final Map<String, Integer> map = someStudents.stream().collect(
            Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

If someStudents is of type Map<String, String> but map is Map<String, Integer> you would get the same:

non-static method Map.Entry::getValue cannot be referenced from a static context

Upvotes: 1

lupchiazoem
lupchiazoem

Reputation: 8086

Firstly, you are accessing getFirstName using a class name -Student(as if its a static memeber) rather than using object reference. Java tutorial - Method Refrences.
Secondly, second parameter of toMap method must be a Function type.

So, the correct statement is:
someStudents.stream().collect( Collectors.toMap( student -> student.getFirstName(), student -> 1 ) );

Edit:
Or, it can also be as posted by @Aomine. Both answers are correct. For more info, refer to comments on @Aomine's answers.

Edit 2:
Though, @Aomine's and this answer give expected result, note difference in first parameter.

Upvotes: 4

Ousmane D.
Ousmane D.

Reputation: 56469

The value mapper should be a function, i.e.:

.collect(Collectors.toMap(Student::getFirstName, s -> 1));

The function s -> 1 essentially takes a student as input and returns 1 in this specific case for the map values.

The below code is not valid as the literal value 1 is not a function.

.collect(Collectors.toMap(Student::getFirstName, 1));

Upvotes: 4

Related Questions