import java.text.DecimalFormat;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;
import java.util.Random;
import java.util.stream.Stream;
import java.util.stream.Collectors;
class Main {
private final static List<String> CATEGORIES = List.of("Cheap", "Moderate", "Expensive");
public static void main(String[] args) {
List<Item> items = getItemsList();
Map<String, List<Item>> itemsByName = getItemsByName(items);
Map<String, List<Item>> itemsByCategories = categorizeItems(itemsByName);
// itemsByCategories.entrySet().forEach(item -> System.out.println(item.getKey() + ": " + item.getValue().stream().map(i -> i.getName() + ": " + i.getPrice()).collect(Collectors.joining(", "))));
printReport(itemsByCategories);
}
private static List<Item> getItemsList() {
// Data generation
final int minPrice = 1;
final int maxPrice = 1000;
Random rand = new Random();
return List.of("Mouse", "Keyboard", "Battery", "Laptop", "Pad Mouse", "Ethernet Cable", "Notebook", "Pen")
.stream()
.flatMap(item -> Stream.generate(() -> item).limit(rand.nextInt(20 - 1) + 1))
.map(product -> new Item(product, Math.round(rand.nextDouble(minPrice, maxPrice) * 100.0) / 100.0))
.toList();
}
private static Map<String, List<Item>> getItemsByName(List<Item> items) {
return items.stream()
.collect(Collectors.groupingBy(item -> item.getName(), TreeMap::new, Collectors.toList()));
}
private static Map<String, List<Item>> categorizeItems(Map<String, List<Item>> items) {
Map<String, List<Item>> itemsByCategories = Map.of("Cheap", new ArrayList<Item>(), "Moderate", new ArrayList<Item>(), "Expensive", new ArrayList<Item>());
items.values().stream().flatMap(List::stream).forEach(item -> {
if (item.getPrice() < 20.0) {
var cheap = itemsByCategories.get("Cheap");
cheap.add(item);
} else if (item.getPrice() >= 20 && item.getPrice() <= 100) {
var moderate = itemsByCategories.get("Moderate");
moderate.add(item);
} else {
var expensive = itemsByCategories.get("Expensive");
expensive.add(item);
}
});
return itemsByCategories;
}
public static void printReport(Map<String, List<Item>> itemsByCategories) {
final DecimalFormat decimalFormatter = new DecimalFormat("0.00");
String output = CATEGORIES.stream().map(category -> {
var itemsByCategory = itemsByCategories.get(category);
StringBuilder message = new StringBuilder();
message.append("Category: ");
message.append(category);
message.append("\n");
message.append("Total Items: ");
message.append(itemsByCategory.size());
message.append("\n");
var discount = 0.0;
var totalByCategory = 0.0;
var totalDiscount = 0.0;
var totalAfterDiscount = 0.0;
if (itemsByCategory.size() > 0) {
if (category.equals("Cheap")) {
discount = 0.05;
} else if (category.equals("Moderate")) {
discount = 0.1;
} else if (category.equals("Expensive")) {
discount = 0.15;
}
totalByCategory = itemsByCategory.stream().map(Item::getPrice).collect(Collectors.summingDouble(n -> n));
totalDiscount = totalByCategory * discount;
totalAfterDiscount = totalByCategory - totalDiscount;
}
message.append("Total Discount: ");
message.append(decimalFormatter.format(totalDiscount));
message.append("\n");
message.append("Total After Discount: ");
message.append(decimalFormatter.format(totalAfterDiscount));
return message.toString();
})
.collect(Collectors.joining("\n\n"));
System.out.println(output);
}
}
class Item {
private String name;
private double price;
// constructor, getters, setters
public Item(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return this.name;
}
public double getPrice() {
return this.price;
}
}