核⼼考点:
对象聚合(订单包含商品列表)、 MapString, ListOrder>> 、销量 / 营业额 统计、Stream ⾼阶⽤法
题⽬要求: 1. Item (商品):名称、单价、数量 → 提供⼩计⾦额⽅法; 2. Order (订单):订单号、⽤户 ID、商品列表 ListItem> → 提供订单总⾦额⽅法; 3. 按⽤户 ID分组订单(Map:⽤户→订单列表); 4. 统计:每个⽤户总消费、平台总营业额、销量最⾼的商品。
打印结果: =====⽤户消费统计===== ⽤户U002 总消费:3999.00元 ⽤户U001 总消费:7096.00元 平台总营业额:11095.00元 销量最⾼商品:⼿机,总销量:2
思路分析:
一、Item 类(商品)
class Item {
private String name; // 商品名:手机、电脑
private double price; // 单价
private int count; // 购买数量
// 小计金额 = 单价 × 数量(题目要求必须提供的方法)
public double getSubtotal() {
return price * count;
}
// 构造方法:创建商品时传入 名称、单价、数量
public Item(String name, double price, int count) {
this.name = name;
this.price = price;
this.count = count;
}
// getter:外部要读取商品信息必须用get
public String getName() { return name; }
public int getCount() { return count; }
}
核心思路
- Item 是基础数据单元,只负责自己的单价、数量、小计。
getSubtotal()是题目强制要求:单个商品的总价。- 提供 getter,让外部类(Order)能读取商品名称、数量。
二、Order 类(订单)
class Order {
private String orderId; // 订单编号 O001
private String userId; // 用户编号 U001
private List<Item> itemList; // 一个订单包含多个商品 → 对象聚合!
// 订单总金额 = 所有商品的小计加起来(题目要求)
public double getTotalAmount() {
return itemList.stream()
.mapToDouble(Item::getSubtotal) // 把每个商品转成小计金额
.sum(); // 求和
}
// 构造方法:创建订单时传入 订单号、用户ID、商品列表
public Order(String orderId, String userId, List<Item> itemList) {
this.orderId = orderId;
this.userId = userId;
this.itemList = itemList;
}
// getter
public String getUserId() { return userId; }
public List<Item> getItemList() { return itemList; }
}
核心思路
-
对象聚合(核心考点)
- 一个订单 包含 多个商品
- 代码体现:
List<Item> itemList
-
getTotalAmount()订单总金额- 流处理商品列表
mapToDouble(Item::getSubtotal):把每个商品 → 金额sum():把所有金额加起来 = 订单总价
三、主程序:完整执行流程(最关键)
第 1 步:构造测试数据
// 商品
Item phone = new Item("手机", 1999, 1);
Item phone2 = new Item("手机", 1999, 1);
Item computer = new Item("电脑", 5099, 1);
Item earphone = new Item("耳机", 1999, 1);
// 订单
Order o1 = new Order("O001", "U001", Arrays.asList(phone, computer));
Order o2 = new Order("O002", "U001", Arrays.asList(earphone));
Order o3 = new Order("O003", "U002", Arrays.asList(phone2));
// 所有订单放到一个集合里
List<Order> orderList = Arrays.asList(o1, o2, o3);
思路
- 先造商品
- 再造订单,订单里装入商品
- 最后把所有订单放到
orderList,方便统一处理
第 2 步:按用户 ID 分组订单(Map<String, List<Order>>)
Map<String, List<Order>> userOrderMap = orderList.stream()
.collect(Collectors.groupingBy(Order::getUserId));
思路(Stream 分组核心)
groupingBy(Order::getUserId)- 按照 userId 分组
- key = 用户 ID
- value = 这个用户的所有订单列表
第 3 步:统计每个用户总消费
userOrderMap.forEach((userId, orders) -> {
double total = orders.stream()
.mapToDouble(Order::getTotalAmount) // 每个订单 → 金额
.sum(); // 求和 = 该用户总消费
System.out.printf("用户%s 总消费:%.2f元%n", userId, total);
});
思路
- 遍历每个用户
- 把该用户的所有订单金额加起来
- 输出格式化结果
第 4 步:统计平台总营业额
double platformTotal = orderList.stream()
.mapToDouble(Order::getTotalAmount)
.sum();
System.out.printf("平台总营业额:%.2f元%n", platformTotal);
思路
- 把所有订单的金额加起来
- 就是平台总营业额
- 最简单的统计
第 5 步:统计销量最高的商品(最难!Stream 高阶)
第一步:把所有订单里的商品全部展开
orderList.stream()
.flatMap(order -> order.getItemList().stream())
思路
flatMap= 扁平化- 把:
订单1[商品1,商品2]、订单2[商品3]变成:[商品1,商品2,商品3]
第二步:按商品名统计总销量
.collect(Collectors.groupingBy(
Item::getName, // 按商品名分组
Collectors.summingInt(Item::getCount) // 每组数量求和
));
得到一个 Map:
- 手机 → 2
- 电脑 → 1
- 耳机 → 1
第三步:找出销量最大的那个
Map.Entry<String, Integer> topItem = itemSalesMap.entrySet().stream()
.max(Map.Entry.comparingByValue()) // 按销量值比较,取最大
.orElse(null);
思路
- 比较 Map 里的 value(销量)
- 取出最大的那一组
- 最后打印商品名 + 销量