You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java Stream实现多表关联获取Top5高分平均电影并按预算排序?

问题描述

我拥有三张关联表:user、movie和score:

User表

id   | name  |
--------------
1    | Hans  |
2    | Carry |

Movie表

id   | name  | budget |
----------------------
101  | Mov 1 | 200    |
102  | Mov 2 | 500    |
103  | Mov 2 | 300    |

Score表

user_id   | movie_id  | score  |
--------------------------------
1         | 101       | 7      |
2         | 101       | 8      |
1         | 102       | 6      |
2         | 102       | 9      |

我希望找出平均评分最高的5部电影,再按其预算进行排序。请问能否使用Java Stream实现该需求?具体如何获取这样的列表?若无法实现,是否应使用查询并通过投影获取数据?


解决方案

完全可以用Java Stream实现这个需求,前提是你已经在内存中加载了三张表对应的实体类数据(比如User、Movie、Score对象集合),以下是具体实现步骤:

1. 实体类定义(示例)

先假设你有对应的实体类结构:

// User类
public class User {
    private Long id;
    private String name;
    // 构造器、getter、toString方法省略
}

// Movie类
public class Movie {
    private Long id;
    private String name;
    private Integer budget;
    // 构造器、getter、toString方法省略
}

// Score类
public class Score {
    private Long userId;
    private Long movieId;
    private Integer score;
    // 构造器、getter、toString方法省略
}

2. Stream实现逻辑

核心思路是先通过Score集合计算每部电影的平均评分,再关联Movie数据完成筛选排序:

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class MovieScoreProcessor {
    public static List<Movie> getTop5Movies(List<Score> scores, List<Movie> movies) {
        // 第一步:计算每部电影的平均评分,key为movieId,value为平均分
        Map<Long, Double> movieAvgScoreMap = scores.stream()
                .collect(Collectors.groupingBy(Score::getMovieId,
                        Collectors.averagingInt(Score::getScore)));

        // 第二步:关联电影数据,按规则排序后取前5
        return movies.stream()
                // 只保留有评分记录的电影
                .filter(movie -> movieAvgScoreMap.containsKey(movie.getId()))
                // 先按平均评分降序,再按预算升序排序(可根据需求调整预算排序方向)
                .sorted(Comparator.comparing((Movie m) -> movieAvgScoreMap.get(m.getId()))
                        .reversed()
                        .thenComparing(Movie::getBudget))
                .limit(5)
                .collect(Collectors.toList());
    }
}

3. 场景选择建议

  • 如果数据量较小(比如万级以内),用Java Stream在内存处理是高效且便捷的;
  • 如果数据量较大(百万级及以上),更建议直接用SQL查询,通过投影获取所需数据,避免内存占用过高。示例SQL如下:
SELECT m.id, m.name, m.budget, AVG(s.score) AS avg_score
FROM movie m
JOIN score s ON m.id = s.movie_id
GROUP BY m.id, m.name, m.budget
ORDER BY avg_score DESC, m.budget ASC
LIMIT 5;

内容的提问来源于stack exchange,提问作者Jack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:40:27