Java Stream 分组并求和

Java 8 引入了 Stream API,使得对集合数据进行操作更加方便和高效。Stream API 提供了丰富的操作方法,其中一个常用的功能是分组并求和。本文将介绍如何使用 Java Stream 对集合进行分组并求和操作,并给出相应的代码示例。

Stream API 简介

Stream 是 Java 8 中新增的一个用于处理集合数据的 API。它可以让我们以函数式编程的方式对集合进行处理,提供了一套丰富的操作方法,如映射、过滤、排序等。Stream API 的设计思想是将集合数据看作一系列的管道,可以通过不同的操作方法来进行数据的处理和转换。

Stream API 的核心是 Stream 接口,它定义了一系列操作方法,可以分为两大类:中间操作和终端操作。中间操作用于对数据进行处理和转换,可以多次调用;终端操作用于触发数据处理的执行,并返回最终结果。

分组并求和操作

分组并求和是一种常见的数据处理需求。例如,我们有一组订单数据,每个订单包含商品名称和销售额。我们希望按照商品名称对订单进行分组,并计算每个商品的销售总额。使用 Stream API,可以很方便地实现这个功能。

首先,我们需要定义一个订单类,包含商品名称和销售额两个属性:

public class Order {
    private String productName;
    private double salesAmount;

    public Order(String productName, double salesAmount) {
        this.productName = productName;
        this.salesAmount = salesAmount;
    }

    // getters and setters
}

接下来,我们创建一组订单数据,并使用 Stream API 对其进行分组并求和操作:

List<Order> orders = Arrays.asList(
        new Order("Apple", 100.0),
        new Order("Banana", 200.0),
        new Order("Apple", 300.0),
        new Order("Banana", 400.0)
);

Map<String, Double> sumByProduct = orders.stream()
        .collect(Collectors.groupingBy(Order::getProductName, Collectors.summingDouble(Order::getSalesAmount)));

System.out.println(sumByProduct);

上述代码首先创建了一个包含四个订单的列表。然后,我们通过 stream() 方法将列表转换为 Stream 对象,并使用 collect() 方法对订单进行分组操作。其中,groupingBy() 方法用于按照商品名称进行分组,summingDouble() 方法用于对每个分组中的销售额进行求和。最后,我们将分组并求和的结果保存在一个 Map 对象中,并输出结果:

{Apple=400.0, Banana=600.0}

可以看到,通过 Stream API,我们很方便地对订单数据进行了分组并求和操作。

分组并求和的应用场景

分组并求和操作在实际应用中非常常见。它可以用于统计销售数据、计算各类指标等。下面以一个具体的示例来说明分组并求和的应用。

假设我们有一个电商平台,有多个商品类别和多个商家。我们希望统计每个商品类别下每个商家的订单销售总额。首先,我们定义一个商品类别和商家的类:

public class Product {
    private String category;
    private String name;

    public Product(String category, String name) {
        this.category = category;
        this.name = name;
    }

    // getters and setters
}

public class Merchant {
    private String name;

    public Merchant(String name) {
        this.name = name;
    }

    // getters and setters
}

然后,我们创建一组订单数据,并进行分组并求和操作:

List<Order> orders = Arrays.asList(
        new Order("Apple", 100.0),
        new Order("Banana", 200.0),
        new Order("Apple", 300.0),
        new Order("Banana", 400.0)
);

Map<Product, Map<Merchant, Double>> sumByCategoryAndMerchant = orders.stream()
        .collect(Collectors.groupingBy(
                order -> new Product(order.getProductName(), "Category"),
                Collectors.groupingBy(
                        order -> new Merchant("Merchant"),
                        Collectors.summingDouble(Order::getSalesAmount)
                )
        ));

System.out.println(sumByCategoryAndMerchant);