import java.util.Arrays;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
class Main {
public static void main(String[] args) {
List<Sale> sales = Arrays.asList(
new Sale(LocalDate.of(2023, 1, 15), "Electronics", 1200.0),
new Sale(LocalDate.of(2023, 2, 20), "Electronics", 800.0),
new Sale(LocalDate.of(2022, 12, 5), "Furniture", 1500.0),
new Sale(LocalDate.of(2023, 3, 10), "Clothing", 300.0),
new Sale(LocalDate.of(2022, 11, 25), "Electronics", 950.0),
new Sale(LocalDate.of(2023, 1, 30), "Furniture", 2000.0)
);
SalesAnalyzer salesAnalyzer = new SalesAnalyzerImpl();
System.out.println("averageByCategory: " + salesAnalyzer.averageByCategory(sales));
System.out.println("totalByYear: " + salesAnalyzer.totalByYear(sales));
System.out.println("largeSalesByCategory: " + salesAnalyzer.largeSalesByCategory(sales));
}
}
class Sale {
private LocalDate saleDate;
private String category;
private double amount;
// constructor, getters
public Sale(LocalDate saleDate, String category, double amount) {
this.saleDate = saleDate;
this.category = category;
this.amount = amount;
}
public LocalDate getSaleDate() {
return this.saleDate;
}
public String getCategory() {
return this.category;
}
public double getAmount() {
return this.amount;
}
}
interface SalesAnalyzer {
/**
* Returns map: category -> average sale amount (rounded to 2 decimals)
* Sorted by category name
*/
Map<String, Double> averageByCategory(List<Sale> sales);
/**
* Returns map: year -> total sales for that year
* Year from saleDate (LocalDate)
* Sorted by year ascending
*/
Map<Integer, Double> totalByYear(List<Sale> sales);
/**
* Returns map: category -> list of sale amounts > 1000
* Sorted by category
* Amounts in original order
*/
Map<String, List<Double>> largeSalesByCategory(List<Sale> sales);
}
class SalesAnalyzerImpl implements SalesAnalyzer {
/**
* Returns map: category -> average sale amount (rounded to 2 decimals)
* Sorted by category name
*/
@Override
public Map<String, Double> averageByCategory(List<Sale> sales) {
Map<String, Double> salesAverages = sales.stream()
.collect(Collectors.groupingBy(Sale::getCategory, TreeMap::new, Collectors.averagingDouble(sale -> sale.getAmount())));
Map<String, Double> salesAveragesFormatted = new TreeMap<>();
salesAverages.entrySet().forEach(entry -> salesAveragesFormatted.put(entry.getKey(), Math.round(entry.getValue() * 100.0) / 100.0));
return salesAveragesFormatted;
}
/**
* Returns map: year -> total sales for that year
* Year from saleDate (LocalDate)
* Sorted by year ascending
*/
@Override
public Map<Integer, Double> totalByYear(List<Sale> sales) {
return sales.stream()
.collect(Collectors.groupingBy(sale -> sale.getSaleDate().getYear(), TreeMap::new, Collectors.summingDouble(Sale::getAmount)));
}
/**
* Returns map: category -> list of sale amounts > 1000
* Sorted by category
* Amounts in original order
*/
@Override
public Map<String, List<Double>> largeSalesByCategory(List<Sale> sales) {
return sales.stream()
.filter(sale -> sale.getAmount() > 1000.0)
.collect(Collectors.groupingBy(Sale::getCategory, TreeMap::new, Collectors.mapping(sale -> sale.getAmount(), Collectors.toList())));
}
}