MST

星途 面试题库

面试题:Java Stream collect方法在复杂业务场景下的数据批量运算及性能优化

假设有一个非常大的订单数据集,订单类Order包含属性orderId(订单ID)、customerId(客户ID)、orderAmount(订单金额)。要求使用Java Stream的collect方法,按照客户ID分组,计算每个客户的总订单金额,并返回订单金额最高的前10个客户及其总订单金额。同时,阐述在处理大数据量时,如何优化这段代码的性能。
39.2万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
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()));
    }
}

性能优化:

  1. 并行流
    • 在大数据量情况下,可以将流操作改为并行流,通过orders.parallelStream()替换orders.stream()。并行流利用多线程并行处理数据,提高处理速度。但要注意并行流可能带来线程安全问题和额外的线程管理开销,在数据量较小或操作有状态依赖时,并行流可能反而降低性能。
  2. 避免中间操作创建大对象
    • 在流操作过程中,尽量避免中间操作创建大的中间对象。如上述代码的groupingBy操作,Collectors.summingDouble方法直接进行累加计算,而不是先收集所有订单金额再求和,减少了内存占用。
  3. 分批处理
    • 如果数据量太大无法一次性加载到内存,可以考虑分批读取数据。例如从数据库读取数据时,使用分页技术每次读取一部分数据,对每批数据进行上述流操作,最后合并结果。
  4. 数据预处理
    • 在进行流操作之前,可以对数据进行一些预处理,如过滤掉不必要的数据,减少流操作的数据量。例如,如果已知某些客户ID不在关注范围内,可以先过滤掉这些客户的订单数据。