Фрагмент кода на языке Java с использованием Stream API

Буду очень благодарен за помощь новичку в написании следующего фрагмента кода на языке Java:
Задание заключается в написании кода с использованием Stream API.
Согласно заданию я реализовал навигационное меню условного интернет магазина состоящее из следующих окон:

  • "Каталог" (состоящий из 4-х товарных позиций),
  • "Корзина",
  • "Оформление заказа". Я застопорился на реализации окна "Назад".
    На печать должно быть выведено следующее:
Наименование: Nokia 3310, Цена: 12345, Кол-во ед. в наличии на складе: 4.
Наименование: Samsung Galaxy S100, Цена: 30000, Кол-во ед. в наличии на складе: 5.
Наименование: IPhone 20, Цена: 392049, Кол-во ед. в наличии на складе: 1.
Наименование: Google Pixel 10a, Цена: 30000, Кол-во ед. в наличии на складе: 0.

Т.е. доступное количество на складе (переменная int qtyInStock) – должно быть 5 только у одной позиции: Samsung Galaxy S100 (изначально в каталоге было 7, заказали: 2, после этого осталось: 5).
У остальных позиций доступное количество на складе должно остаться неизменным, таким, какое было изначально в каталоге.
Предполагаю, что должно быть использовано сочетание методов maр и if.


import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
    
public class Main {
    public static void main(String[] args) {
        System.out.println("""
                Задание:\s
                Урок 20. Задание с использованием Stream Api.
                    Реализовать навигационное меню состоящее из:
                    Каталог
                    Корзина
                    Оформление заказа
                    Назад

                Решение:\s""");
    
        Products prod1 = new Products("Nokia 3310", 12345, 4, 0);
        Products prod2 = new Products("Samsung Galaxy S100", 30000, 7, 0);
        Products prod3 = new Products("IPhone 20", 392049, 1, 0);
        Products prod4 = new Products("Google Pixel 10a", 30000, 0, 0);
        List<Products> catalog = new ArrayList<>();
        catalog.add(prod1);
        catalog.add(prod2);
        catalog.add(prod3);
        catalog.add(prod4);
    
        System.out.println("\nРЕАЛИЗУЕМ НАВИГАЦИОННОЕ МЕНЮ, СОСОЯЩЕЕ ИЗ РАЗДЕЛОВ:");
        System.out.println("ПОЛНЫЙ КАТАЛОГ:");
        catalog.stream()
            .map((product -> "Наименование: " + product.getName() + ", " 
                + "Цена: " + product.getPrice() + ", " 
                + "Кол-во ед. в наличии на складе: " + product.getQtyInStock() + "."
            ))
            .forEach(System.out::println);
        System.out.println();
    
        System.out.println("КОРЗИНА: \n(Выбрано: Samsung Galaxy S100 - 2 шт.)");
        catalog.stream()
            .filter(element -> Objects.equals(element.getName(), "Samsung Galaxy S100"))
            .map((product -> "Наименование: " + product.getName() + ", " 
                + "Цена: " + product.getPrice() /*+ ", " 
                + "Кол-во ед. в наличии на складе: " + product.getQtyInStock() */+ ", " 
                + "Кол-во заказано: " + (product.getQtyOrdered()+2) + "."))
            .forEach(System.out::println);
        System.out.println();
    
        System.out.println("ОФОРМЛЕНИЕ ЗАКАЗА:");
        catalog.stream()
            .filter(element -> Objects.equals(element.getName(), "Samsung Galaxy S100"))
            .map((product -> "Наименование: " + product.getName() + ", " 
                + "Цена: " + product.getPrice() /*+ ", " + "Кол-во ед. в наличии на складе: " + product.getQtyInStock() */
                + ", " + "Кол-во заказано: " +
                (product.getQtyOrdered()+2) + ", " 
                +  "Итого сумма к оплате: " + product.getPrice()*2 + " руб."))
            .forEach(System.out::println);
        System.out.println();
    
        System.out.println("НАЗАД:");
    
    }
}
class Products {
    private String name;
    private int price;
    private int qtyInStock;
    private int qtyOrdered;
    
    
    public Products(String name, int price, int qtyInStock, int qtyOrdered) {
        this.setName(name);
        this.setPrice(price);
        this.setQtyInStock(qtyInStock);
        this.setQtyOrdered(qtyOrdered);
    }
// геттеры/сеттеры
    
    @Override
    public String toString() {
        return "Products{" +
            "name='" + name + '\'' +
            ", price=" + price +
            ", qtyInStock=" + qtyInStock +
            ", qtyOrdered=" + qtyOrdered +
        '}';
    }
}

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

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

Название меню "Назад" не слишком соответствует ожидаемому выводу: фактически, должно быть просто ещё раз распечатано содержимое каталога, после того как должно было измениться количество телефонов на складе, в результате выполнения двух предыдущих пунктов "Корзина" (увеличивается qtyOrdered) и "Оформление заказа" (qtyInStock уменьшается на величину qtyOrdered, qtyOrdered сбрасывается в 0).

Исправленный код может выглядеть следующим образом с некоторыми дополнительными изменениями:

  • Для вывода содержимого каталога лучше использовать форматированный вывод System.out.printf вместо map со множеством конкатенаций.
  • Название и количество товара, добавляемого в корзину, лучше вынести в отдельные переменные.
  • Используется метод Stream API findFirst для поиска нужного товара.
  • Товары переименованы в соответствии с их названиями, список catalog создан при помощи Arrays.asList (или List.of).
  • В класс Products добавлен метод sell, чтобы изменить количество товара на складе и в заказе:
// class Products
public void sell() {
    this.qtyInStock -= this.qtyOrdered;
    this.qtyOrdered = 0;
}

Остальные изменения -- в методе Main.main:

Products nokia = new Products("Nokia 3310", 12345, 4, 0);
Products samsungGalaxy = new Products("Samsung Galaxy S100", 30000, 7, 0);
Products iphone = new Products("IPhone 20", 392049, 1, 0);
Products googlePixel = new Products("Google Pixel 10a", 30000, 0, 0);
List<Products> catalog = Arrays.asList(nokia, samsungGalaxy, iphone, googlePixel);

System.out.println("\nРЕАЛИЗУЕМ НАВИГАЦИОННОЕ МЕНЮ, СОСТОЯЩЕЕ ИЗ РАЗДЕЛОВ:");
System.out.println("ПОЛНЫЙ КАТАЛОГ:");
catalog.forEach(p -> System.out.printf("Наименование: %s, Цена: %d, Кол-во на складе: %d.%n", 
    p.getName(), p.getPrice(), p.getQtyInStock())
);
System.out.println();

String name = "Samsung Galaxy S100";
int count = 2;

System.out.printf("КОРЗИНА: \n(Выбрано:  %s- %d шт.)%n", name, count);

// нашли продукт
Products selected = catalog.stream()
    .filter(product -> Objects.equals(product.getName(), name))
    .filter(product -> product.getQtyInStock() >= count)
    .findFirst()
    .orElseThrow(() -> new IllegalStateException("Товар не найден"));
// изменили состояние при заказе
selected.setQtyOrdered(count);
// распечатали содержимое корзины
catalog
    .stream()
    .filter(product -> product.getQtyOrdered() > 0)
    .forEach(p -> System.out.printf("Наименование: %s, Цена: %d, Кол-во заказа: %d.%n", 
        p.getName(), p.getPrice(), p.getQtyOrdered()
    ));
System.out.println();

System.out.println("ОФОРМЛЕНИЕ ЗАКАЗА:");
catalog.stream()
    .filter(product -> Objects.equals(product.getName(), name)) // product.getQtyOrdered() > 0
    .forEach(p -> System.out.printf("Наименование: %s, Цена: %d, Кол-во заказа: %d, Сумма к оплате: %d руб.%n", 
        p.getName(), p.getPrice(), p.getQtyOrdered(), p.getPrice() * p.getQtyOrdered()
    ));
System.out.println();
// изменили состояние после оформления заказа, т.е. покупки
selected.sell();

System.out.println("НАЗАД:");
catalog.forEach(p -> System.out.printf("Наименование: %s, Цена: %d, Кол-во на складе: %d.%n", 
    p.getName(), p.getPrice(), p.getQtyInStock())
);

Разумеется, данную задачу можно было бы реализовать корректно с точки зрения ООП, создав отдельный класс Shop, с методами, соответствующими указанным пунктам меню (командам), которые и следовало бы вызывать после создания экземпляра магазина.

public class Shop {
    private List<Products> stock;

    public Shop(List<Products> products) {
        this.stock = new ArrayList<>(products);
    }

    // Каталог
    public void inventory() {
        // вывести каталог товаров
    }

    // Корзина
    public void putToCart(String name, int count) {
        // добавить в "корзину", распечатать её содержимое
    }

    // Оформить заказ
    public void completeOrder() {
        // изменить состояние склада
    }
// ...
}
→ Ссылка