Фрагмент кода на языке 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 шт):
Название меню "Назад" не слишком соответствует ожидаемому выводу: фактически, должно быть просто ещё раз распечатано содержимое каталога, после того как должно было измениться количество телефонов на складе, в результате выполнения двух предыдущих пунктов "Корзина" (увеличивается 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() {
// изменить состояние склада
}
// ...
}