Java - Как фильтровать по значению (список)

Я постараюсь объяснить как можно лучше. Представим, что у меня есть этот класс:

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> >

Спасибо за внимание :)

Student::clone возвращает Object, а не Student.
Eran 03.06.2018 15:39

Что является ключом к желаемой карте результатов?

user7 03.06.2018 15:42

@Eran, поскольку clone() может быть вызван только в том случае, если он переопределен Student, мы не можем сказать, возвращает ли он Object или что-то еще. Он может вернуть что-нибудь. Отсутствие implements Cloneable в классе Student говорит о том, что он вообще не делегируется Object.clone(). Но независимо от того, что он возвращает, компилятору нет причин жаловаться на .map(Student::clone), поскольку нет никаких ограничений в отношении того, что возвращает функция сопоставления.

Holger 04.06.2018 10:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
107
2

Ответы 2

Первая проблема, вам не нужно использовать 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).

Ousmane D. 03.06.2018 16:12

Привет, сэр, спасибо за ответ, на самом деле мне очень помогло :)

CellScript 03.06.2018 17:44

если все, что вы хотите сделать, это фильтр, тогда вам не нужен .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 03.06.2018 23:07

@dehasi нет, как указано в моем ответе, если у вас есть конструктор копирования как таковой Student(Student s){...}, то .map(Student::new) совпадает с .map(s -> new Student(s)).

Ousmane D. 03.06.2018 23:15

Другие вопросы по теме