Помогите написать лямбда выражение по данному заданию

У меня не получается выйти на книги и продолжить работу с ними

Задание:

  1. Реализовать собственный аналог HashSet с двумя методами (вставить и удалить) и аналог ArrayList/LinkedList (листы на выбор, но должны быть основные методы add, get, remove, addAll)

  2. Создать класс Student, обязательное поле класса Student - List<Book> (минимум по 5 книг у каждого)

  3. Заполнить коллекцию студентами

  4. При помощи одного (не допускается объявления никаких промежуточных переменных, совсем никаких) стрима:

    • Вывести в консоль каждого студента (переопределите toString)
    • Получить для каждого студента список книг
    • Получить книги
    • Отсортировать книги по количеству страниц (Не забывайте про условия для сравнения объектов)
    • Оставить только уникальные книги
    • Отфильтровать книги, оставив только те, которые были выпущены после 2000 года
    • Ограничить стрим на 3 элементах
    • Получить из книг годы выпуска
    • При помощи методов короткого замыкания (почитайте самостоятельно что это такое) вернуть Optional от книги
    • При помощи методов получения значения из Optional вывести в консоль год выпуска найденной книги, либо запись о том, что такая книга отсутствует
public class Main {
    public static void main(String[] args) {
        List<Student> students = (List<Student>) new MyArrayList<>();

        MyHashSet<Books> hashSet = new MyHashSet<Books>();

        Student misha = new Student("Миша");
        misha.getList().add(new Books("Гарри Поттер 1", 2000, 150));
        misha.getList().add(new Books("Гарри Поттер 2", 2001, 160));
        misha.getList().add(new Books("Колобок", 1988, 15));
        misha.getList().add(new Books("Пёс", 2010, 102));
        misha.getList().add(new Books("Психология", 1985, 222));

        Student pasha = new Student("Паша");
        pasha.getList().add(new Books("Гарри Поттер 1", 2000, 150));
        pasha.getList().add(new Books("Гарри Поттер 2", 2001, 160));
        pasha.getList().add(new Books("Гарри Поттер 3", 202, 170));
        pasha.getList().add(new Books("Да Лис", 2010, 103));
        pasha.getList().add(new Books("Неврология", 1985, 222));

        students.add(misha);
        students.add(pasha);

        students.stream().peek(s -> {
           s.toString();
           s.getList().stream().collect(Collectors.toList())
        });
    }
}

Ответы (1 шт):

Автор решения: Nowhere Man

Судя по коду, в нём выполнены три первых пункта задания и осталось реализовать последний четвёртый пункт при помощи одного и того же стрима, и проблема возникла уже на выводе каждого студента в консоль.

Исходный вопрос не слишком корректный, так как здесь не требуется писать особой "лямбды", а достаточно расписать последовательность операций над стримом, как показано ниже.

Полный готовый код не приводится в педагогических целях


Для вывода каждого студента в консоль достаточно было бы передать в метод Stream::peek ссылку на метод System.out::println, который и будет вызывать переопределённый метод toString для каждого студента в стриме.

students.stream() // Stream<Student>
    .peek(System.out::println)  // вывод каждого студента, сохраняется Stream<Student>

Использование ссылок на метод позволяет избежать объявления промежуточных переменных:

.peek(s -> System.out.println(s)) то же самое, что .peek(System.out::println)

После операции peek в том же стриме следует использовать другие операции, включая обязательную терминальную/конечную (terminal) операцию (иначе peek не будет вызван, как и другие промежуточные (intermediate) операции):

  • Получить для каждого студента список книг

Использовать Stream::map: .map(Student::getBooks) // Stream<List<Books>>

  • Получить книги

Т.е. преобразовать стрим списков книг в один стрим книг при помощи Stream::flatMap и ссылки на метод List::stream, после этого шага будет Stream<Books>

  • Отсортировать книги по количеству страниц (Не забывайте про условия для сравнения объектов)

Использовать Stream::sorted(Comparator<? super T> comparator) с компаратором Comparator.comparingInt(Books::getPages)

  • Оставить только уникальные книги

Использовать Stream::distinct

  • Отфильтровать книги, оставив только те, которые были выпущены после 2000 года

Использовать Stream::filter, например: .filter(book -> book.getYear() > 2000)

  • Ограничить стрим на 3 элементах

Использовать Stream::limit

  • Получить из книг годы выпуска

Снова использовать Stream::map со ссылкой на соответствующий метод класса Books, получив в результате Stream<Integer>

  • При помощи методов короткого замыкания (почитайте самостоятельно что это такое) вернуть Optional от книги

Использовать терминальную операцию Stream::findFirst / Stream::findAny.
Здесь есть небольшая неточность в задании -- будет получен Optional<Integer> от года выпуска

  • При помощи методов получения значения из Optional вывести в консоль год выпуска найденной книги, либо запись о том, что такая книга отсутствует

Здесь лучше использовать метод Optional::isPresentOrElse(Consumer<? super T> action, Runnable emptyAction) (Java 9+):
.ifPresentOrElse(System.out::println, ()-> System.out.println("Книга отсутствует"))

В итоге должен быть напечатан год выпуска книги с наименьшим количеством страниц, изданной после 2000 года.

→ Ссылка