Я постараюсь объяснить как можно лучше. Представим, что у меня есть этот класс:
public class Student {
public String nome;
public int number;
public int age;
public int grade;
}
Теперь у меня будет карта, определенная как:
Map<String, Student> students;
Я хочу найти студентов с оценкой> = 10, и я сделал что-то вроде этого:
public List<Student> grade() {
return students.values()
.stream()
.filter(Student::verifyGrade)
.map(Student::clone)
.collect(Collectors.toList());
}
Вот и первая проблема:
- Я получаю сообщение об ошибке «несовместимые типы: невозможно определить переменную типа R» в .map (Student :: clone).
2-я проблема: Теперь, если моя карта определила что-то вроде: (Это просто пример, о котором я думал), как я буду фильтровать с тем же стилем на 1-м?
Map<String, List<Student> >
Спасибо за внимание :)
Что является ключом к желаемой карте результатов?
@Eran, поскольку clone() может быть вызван только в том случае, если он переопределен Student, мы не можем сказать, возвращает ли он Object или что-то еще. Он может вернуть что-нибудь. Отсутствие implements Cloneable в классе Student говорит о том, что он вообще не делегируется Object.clone(). Но независимо от того, что он возвращает, компилятору нет причин жаловаться на .map(Student::clone), поскольку нет никаких ограничений в отношении того, что возвращает функция сопоставления.




Первая проблема, вам не нужно использовать map(Student::clone) после filter:
return students.values()
.stream()
.filter(Student::verifyGrade)
.collect(Collectors.toList());
Вторая проблема, если карта похожа на Map<String, List<Student>>, вы можете использовать flatMap так:
return students.values()
.stream()
.flatMap(List::stream)
.filter(Student::verifyGrade)
.collect(Collectors.toList());
Что ж, если, автор метода grade, осторожно относится к пользователям, изменяющим объекты в возвращенном List<Student>, тогда было бы разумно клонировать объекты Student. Действительно ли это необходимо, зависит от того, о чем думали ОП, когда они решили использовать .map(Student::clone).
Привет, сэр, спасибо за ответ, на самом деле мне очень помогло :)
если все, что вы хотите сделать, это фильтр, тогда вам не нужен .map(Student::clone), но если вам нужно клонировать объекты, то читайте дальше.
Object::clone возвращает тип Object, следовательно, возникает ошибка компиляции, есть обходной путь путем приведения возвращенного Object к типу Person, но вместо этого я бы просто создал конструктор копирования или метод, который копирует содержимое Student в новый экземпляр и возвращает его.
Тогда просто сделайте:
.map(Student::new) // assuming you have a constructor public Student(Student s){...}
или же
.map(Student::copy) // assuming you have a method public static Student copy(Student s){...}
чтобы ответить на ваш второй вопрос:
List<Student> resultSet =
myMap.values()
.stream()
.flatMap(Collection::stream)
.filter(Student::verifyGrade)
.map(Student::new)
.collect(Collectors.toList());
если вам не нужно клонировать объекты Student, просто удалите вызов .map(Student::new).
разве Student::new просто не создал класс со значениями по умолчанию?
@dehasi нет, как указано в моем ответе, если у вас есть конструктор копирования как таковой Student(Student s){...}, то .map(Student::new) совпадает с .map(s -> new Student(s)).
Student::cloneвозвращаетObject, а неStudent.