1

I will try explain as the best I can. Let's imagine I've this class:

public class Student { public String nome; public int number; public int age; public int grade; } 

Now I will have an map defined like:

Map<String, Student> students; 

I will want to find the students with grade >= 10 and I did something like this:

public List<Student> grade() { return students.values() .stream() .filter(Student::verifyGrade) .map(Student::clone) .collect(Collectors.toList()); } 

Here's come the 1st problem:
- I'm getting error "incompatible types: cannot infer type-variable(s) R" on .map(Student::clone).

2nd problem: Now if I've my map defined something like: (It's just a example I was thinking), how I would filter with the same style on 1st?

Map<String, List<Student> > 

Thanks for your attention :)

3
  • 3
    Student::clone returns an Object, not a Student. Commented Jun 3, 2018 at 13:39
  • What is the key of your desired result map? Commented Jun 3, 2018 at 13:42
  • @Eran since clone() can only be called if overridden by Student, we can’t say whether it returns Object or something else. It could return anything. The absence of implements Cloneable at the class Student suggests that it is not even delegating to Object.clone() at all. But whatever it returns, it isn’t any reason for the compiler to complain at .map(Student::clone), as there is no restriction regarding what the mapping function returns. Commented Jun 4, 2018 at 8:23

2 Answers 2

1

First problem you don't need to use map(Student::clone) after filter :

return students.values() .stream() .filter(Student::verifyGrade) .collect(Collectors.toList()); 

Second problem if the Map is like Map<String, List<Student>> you ca use flatMap like so :

return students.values() .stream() .flatMap(List::stream) .filter(Student::verifyGrade) .collect(Collectors.toList()); 
Sign up to request clarification or add additional context in comments.

2 Comments

Well, if the author of the grade method is cautious about users modifying the objects in the List<Student> returned then it would be wise to clone the Student objects. Whether this is really necessary depends on what the OP was thinking when they decided to use .map(Student::clone).
Hey sir, thanks for the answer, it helped me a lot in fact :)
1

if all you want to do is filter then you don't need .map(Student::clone) but if you do need to clone the objects then read on.

Object::clone returns a type Object hence the compilation error, there is a workaround by casting the returned Object to a type Person but instead, I would simply create a copy constructor or a method which copies the content of Student into a new instance and returns it.

Then simply do:

.map(Student::new) // assuming you have a constructor public Student(Student s){...} 

or

.map(Student::copy) // assuming you have a method public static Student copy(Student s){...} 

to answer your second question:

List<Student> resultSet = myMap.values() .stream() .flatMap(Collection::stream) .filter(Student::verifyGrade) .map(Student::new) .collect(Collectors.toList()); 

if you don't need to clone the Student objects then just remove the call to
.map(Student::new).

2 Comments

didn't Student::new just create a class with default values?
@dehasi no, as stated in my answer if you have a copy constructor as such Student(Student s){...} then .map(Student::new) is the same as .map(s -> new Student(s)).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.