import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Order {
private int orderId;
private int customerId;
private double orderAmount;
public Order(int orderId, int customerId, double orderAmount) {
this.orderId = orderId;
this.customerId = customerId;
this.orderAmount = orderAmount;
}
public int getCustomerId() {
return customerId;
}
public double getOrderAmount() {
return orderAmount;
}
}
public class Main {
public static void main(String[] args) {
List<Order> orders = List.of(
new Order(1, 1, 100.0),
new Order(2, 1, 200.0),
new Order(3, 2, 150.0),
// 更多订单数据
new Order(10000, 1000, 50.0)
);
Map<Integer, Double> customerTotalAmount = orders.stream()
.collect(Collectors.groupingBy(
Order::getCustomerId,
Collectors.summingDouble(Order::getOrderAmount)
));
List<Map.Entry<Integer, Double>> top10Customers = customerTotalAmount.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(10)
.collect(Collectors.toList());
top10Customers.forEach(entry -> System.out.println("CustomerId: " + entry.getKey() + ", Total Amount: " + entry.getValue()));
}
}
性能优化:
- 并行流:
- 在大数据量情况下,可以将流操作改为并行流,通过
orders.parallelStream()
替换orders.stream()
。并行流利用多线程并行处理数据,提高处理速度。但要注意并行流可能带来线程安全问题和额外的线程管理开销,在数据量较小或操作有状态依赖时,并行流可能反而降低性能。
- 避免中间操作创建大对象:
- 在流操作过程中,尽量避免中间操作创建大的中间对象。如上述代码的
groupingBy
操作,Collectors.summingDouble
方法直接进行累加计算,而不是先收集所有订单金额再求和,减少了内存占用。
- 分批处理:
- 如果数据量太大无法一次性加载到内存,可以考虑分批读取数据。例如从数据库读取数据时,使用分页技术每次读取一部分数据,对每批数据进行上述流操作,最后合并结果。
- 数据预处理:
- 在进行流操作之前,可以对数据进行一些预处理,如过滤掉不必要的数据,减少流操作的数据量。例如,如果已知某些客户ID不在关注范围内,可以先过滤掉这些客户的订单数据。