使用 Java Stream 进行 Group By 操作并计算字段之和
在这篇文章中,我们将一起学习如何使用 Java Stream API 来对一个 List 进行分组并计算某个字段的总和。对于 Java 开发者来说,掌握流操作是一项非常重要的技能。我们将通过以下步骤来完成这个任务:
步骤 | 描述 |
---|---|
1 | 创建一个示例对象类(如 Order)。 |
2 | 创建一个示例数据列表。 |
3 | 使用 Stream 进行分组。 |
4 | 计算每个组的某个字段总和。 |
5 | 打印结果。 |
接下来,我们将详细讨论每一步的具体实现。
一、创建一个示例对象类
首先,我们需要创建一个对象类。在这个例子中,我们定义一个 Order
类,包含几个基本字段。
public class Order {
private String category; // 订单类别
private double amount; // 订单金额
// 构造函数
public Order(String category, double amount) {
this.category = category;
this.amount = amount;
}
// Getter 方法
public String getCategory() {
return category;
}
public double getAmount() {
return amount;
}
}
解释:
Order
类表示一个订单对象,包含category
和amount
两个字段。- 构造函数用于初始化订单的类别和金额。
- Getter 方法用于获取字段值。
二、创建一个示例数据列表
接下来,我们需要创建一个订单列表以供后续操作。
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Order> orders = new ArrayList<>();
orders.add(new Order("Electronics", 100.0));
orders.add(new Order("Clothing", 50.0));
orders.add(new Order("Electronics", 150.0));
orders.add(new Order("Clothing", 75.0));
orders.add(new Order("Books", 30.0));
// 在此继续实现 Grouping 和 Summation
}
}
解释:
- 我们创建了一个
ArrayList
实例orders
,并向其中添加了一些Order
对象。
三、使用 Stream 进行分组
现在,我们可以使用 Java 8 的 Stream API 进行分组操作了。我们将使用 Collectors.groupingBy
方法来对订单按类别进行分组。
import java.util.Map;
import java.util.stream.Collectors;
// 省略上面的代码
Map<String, List<Order>> groupedOrders = orders.stream()
.collect(Collectors.groupingBy(Order::getCategory));
解释:
orders.stream()
表示将订单列表转化为流。Collectors.groupingBy(Order::getCategory)
表示根据订单的category
字段进行分组,结果是一个以类别为键、订单列表为值的 Map。
四、计算每个组的某个字段总和
接下来,我们需要在分组数据上计算每个组的 amount
字段总和。
Map<String, Double> totalAmounts = groupedOrders.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey, // 取 Map 的键,即类别
entry -> entry.getValue().stream()
.mapToDouble(Order::getAmount) // 提取金额字段
.sum() // 计算金额总和
));
解释:
groupedOrders.entrySet().stream()
将分组后的 Map 转换为流。Collectors.toMap(...)
用于生成一个新的 Map,其中包含类别及其对应的金额总和。entry -> entry.getValue().stream().mapToDouble(Order::getAmount).sum()
表达式用于提取每个类别中订单的金额并计算总和。
五、打印结果
最后,我们将结果打印出来,以验证我们的计算是否正确。
totalAmounts.forEach((category, total) -> {
System.out.println("Category: " + category + ", Total Amount: " + total);
});
解释:
totalAmounts.forEach(...)
用于遍历最终的 Map,并打印每个类别及其对应的金额总和。
总结
通过这篇文章,我们展示了如何使用 Java Stream API 实现对数据的分组和求和。完整示例代码如下所示:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
List<Order> orders = new ArrayList<>();
orders.add(new Order("Electronics", 100.0));
orders.add(new Order("Clothing", 50.0));
orders.add(new Order("Electronics", 150.0));
orders.add(new Order("Clothing", 75.0));
orders.add(new Order("Books", 30.0));
Map<String, List<Order>> groupedOrders = orders.stream()
.collect(Collectors.groupingBy(Order::getCategory));
Map<String, Double> totalAmounts = groupedOrders.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().stream()
.mapToDouble(Order::getAmount)
.sum()
));
totalAmounts.forEach((category, total) -> {
System.out.println("Category: " + category + ", Total Amount: " + total);
});
}
}
// Order 类的实现略
sequenceDiagram
participant User
participant Java_Program
User->>Java_Program: 创建订单列表
Java_Program->>Java_Program: 使用 Stream 分组
Java_Program->>Java_Program: 计算每组总和
Java_Program->>User: 打印结果
通过以上步骤与代码示例,相信你已经掌握了如何使用 Java Stream 进行分组和求和的基本操作。希望这篇文章能够帮助你快速入门并掌握这一实用技巧!