
在实际应用中,我们经常需要处理来自多个关联数据源的信息。本教程将解决一个典型问题:给定用户、电影和评分三张关联表的数据,如何找出平均得分最高的n部电影,并在此基础上,根据电影的预算对这n部电影进行排序。
为了模拟数据,我们定义以下Java record 类型作为数据模型:
// 电影评分记录
record Score(int userId, int movieId, int score) {}
// 电影信息记录
record Movie(int id, String name, int budget) {}假设我们有以下示例数据:
电影数据 (List<Movie>) | id | name | budget | |----|------|--------| | 101| Mov 1| 200 | | 102| Mov 2| 500 | | 103| Mov 3| 300 |
评分数据 (List<Score>) | user_id | movie_id | score | |---------|----------|-------| | 1 | 101 | 6 | | 2 | 101 | 8 | | 1 | 102 | 6 | | 2 | 102 | 9 |
我们的目标是:
Java Stream API提供了一种声明式的方式来处理集合数据,非常适合进行这种多阶段的聚合和转换操作。
立即学习“Java免费学习笔记(深入)”;
首先,我们需要初始化电影和评分数据。为了在后续步骤中能根据 movieId 快速查找 Movie 对象,我们通常会创建一个 Map<Integer, Movie>。
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.Map.Entry; // 注意导入 Map.Entry
public class MovieAnalysis {
public static void main(String[] args) {
// 示例数据初始化
List<Movie> movies = List.of(
new Movie(101, "Mov 1", 200),
new Movie(102, "Mov 2", 500),
new Movie(103, "Mov 3", 300));
List<Score> scores = List.of(
new Score(1, 101, 6),
new Score(2, 101, 8),
new Score(1, 102, 6),
new Score(2, 102, 9));
// 创建电影ID到电影对象的映射,便于后续查找
Map<Integer, Movie> movieMap = movies.stream()
.collect(Collectors.toMap(Movie::id, Function.identity()));
}
}利用 Collectors.groupingBy 和 Collectors.averagingDouble,我们可以轻松地计算出每部电影的平均得分。
// ... (接上文代码)
// 1. 计算每部电影的平均得分
// 结果是一个 Map<Integer, Double>,键是 movieId,值是平均得分
Map<Integer, Double> movieAverageScores = scores.stream()
.collect(Collectors.groupingBy(
Score::movieId, // 按 movieId 分组
Collectors.averagingDouble(Score::score) // 计算每个组的平均得分
));
// movieAverageScores 内容示例:
// {101=7.0, 102=7.5}接下来,我们需要从 movieAverageScores 中找出平均得分最高的N部电影(这里是5部),然后将这些电影对象根据预算进行二次排序。
// ... (接上文代码)
// 2. 筛选平均得分最高的N部电影,并按预算排序
List<Movie> top5Movies = movieAverageScores.entrySet().stream()
// 将 Map 的 Entry 转换为 Stream,Entry 的键是 movieId,值是平均得分
// 2.1 按平均得分降序排序
.sorted(Collections.reverseOrder(Entry.comparingByValue()))
// 2.2 限制只取前5个(平均得分最高的5部电影)
.limit(5)
// 2.3 将 Entry 转换为 Movie 对象:根据 movieId 从 movieMap 中查找对应的 Movie
.map(entry -> movieMap.get(entry.getKey()))
// 2.4 对这5部电影,按预算降序排序
.sorted(Collections.reverseOrder(Comparator.comparing(Movie::budget)))
// 2.5 收集结果到 List
.toList();
// 打印结果
top5Movies.forEach(System.out::println);将上述步骤整合,得到完整的Java Stream解决方案:
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.Map.Entry;
public class MovieAnalysis {
// 电影评分记录
record Score(int userId, int movieId, int score) {}
// 电影信息记录
record Movie(int id, String name, int budget) {}
public static void main(String[] args) {
// 示例数据初始化
List<Movie> movies = List.of(
new Movie(101, "Mov 1", 200),
new Movie(102, "Mov 2", 500),
new Movie(103, "Mov 3", 300));
List<Score> scores = List.of(
new Score(1, 101, 6),
new Score(2, 101, 8),
new Score(1, 102, 6),
new Score(2, 102, 9));
// 1. 创建电影ID到电影对象的映射,便于后续查找
Map<Integer, Movie> movieMap = movies.stream()
.collect(Collectors.toMap(Movie::id, Function.identity()));
// 2. 计算每部电影的平均得分,并找出平均得分最高的N部电影,然后按预算排序
List<Movie> top5Movies = scores.stream()
// 2.1 按 movieId 分组,并计算每组的平均得分
.collect(Collectors.groupingBy(
Score::movieId,
Collectors.averagingDouble(Score::score)))
// 2.2 将 Map 的 Entry 转换为 Stream
.entrySet().stream()
// 2.3 按平均得分降序排序
.sorted(Collections.reverseOrder(Entry.comparingByValue()))
// 2.4 限制只取前5个 Entry
.limit(5)
// 2.5 将 Entry 的 movieId 转换为对应的 Movie 对象
.map(entry -> movieMap.get(entry.getKey()))
// 2.6 对这5部 Movie 对象,按预算降序排序
.sorted(Collections.reverseOrder(Comparator.comparing(Movie::budget)))
// 2.7 收集结果到 List
.toList();
// 打印最终结果
top5Movies.forEach(System.out::println);
}
}根据提供的示例数据,上述代码将输出:
Movie[id=102, name=Mov 2, budget=500] Movie[id=101, name=Mov 1, budget=200]
结果分析:
通过本教程,您应该掌握了如何利用Java Stream API进行复杂的数据聚合、筛选和多条件排序,这对于高效处理内存中的关联数据集具有重要的实践意义。
以上就是使用Java Stream聚合多表数据并按条件排序:以电影评分与预算为例的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号