webprogr.ru Новости

RSS

{{toodo.preview}}

...
{{toodo.name}}

{{toodo.preview}}

далее..

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

смотреть..

toodo.name

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

перейти...

{{toodo.preview}}

...
{{toodo.name}}

{{toodo.preview}}

далее..

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

смотреть..

toodo.name

{{toodo.preview}}

{{toodo.name}}

{{toodo.preview}}

перейти...


Последние новости

Лабораторная работа № VII : Функциональное программирование в Java: лямбда- выражения и Stream API.

(проект лаб , будет правиться по результатам приемки лаб 6)

Лабораторная работа № 7 — «Лямбда-выражения, функциональные интерфейсы и Stream API»

Эта работа превращает уже существующий список транзакций в аналитическую систему.

Сначала студент без Stream API имеет методы:


List<Transaction> findExpenses(...)

BigDecimal totalByCategory(...)

Map<Category, BigDecimal> totals(...)

и затем переписывает их декларативно.

Вводятся стандартные функциональные интерфейсы:


Predicate<Transaction>
Function<Transaction, BigDecimal>
Consumer<Transaction>
Supplier<List<Transaction>>

Лямбды в Java являются средством предоставления реализации функционального интерфейса; официальные материалы Java рассматривают их именно в этой связи.

Обязательные задачи:


найти все расходы за период;
найти операции больше заданной суммы;
отсортировать операции по убыванию суммы;
получить список описаний;
посчитать сумму расходов;
сгруппировать расходы по категории;
найти категорию с максимальными расходами;
получить пять крупнейших расходов.

Например:


var result = transactions.stream()
        .filter(...)
        .sorted(...)
        .limit(5)
        .toList();

Студент должен в каждом pipeline явно пометить:


источник
→ промежуточные операции
→ терминальную операцию

Java Stream API разделяет операции на intermediate и terminal; вычисление pipeline инициируется терминальной операцией, а многие промежуточные операции выполняются лениво.

Эксперимент на ленивость:


Stream<Transaction> stream = transactions.stream()
        .filter(t -> {
            System.out.println("filter: " + t.getId());
            return ...;
        });

// ничего больше не делать

Затем добавить .count() или .toList() и сравнить вывод.

Эксперимент «плохой Stream».

Студенту предлагается:

BigDecimal[] total = {BigDecimal.ZERO};

transactions.stream()
    .forEach(t -> total[0] =
        total[0].add(t.getAmount()));


и требуется переписать без изменяемого внешнего состояния.

parallelStream() — только эксперимент, не “ускоритель”. Студент запускает одну и ту же задачу через stream() и parallelStream(), наблюдает порядок выполнения и объясняет, почему нельзя исходить из правила «parallel всегда быстрее». Официальная документация прямо предупреждает, что функции в stream pipeline должны быть non-interfering/stateless, а порядок forEach в параллельной обработке не гарантируется.

В отчёте обязательно сравниваются императивный и stream-варианты по читаемости, а не только по числу строк.



Вопросы для углубления: Что такое лямбда-выражение и функциональный
интерфейс?Какие задачи решают Predicate,
Function, Consumer и т. п. ?Как устроен конвейер
Stream: промежуточные и терминальные
операции?Что означает «ленивость» вычислений в
Stream API?В чем особенности и риски
parallelStream()?
Рейтинг@Mail.ru