Java中使用Stream根据ID合并电影与分类列表的实现方法
用Java Stream实现电影与分类数据的关联合并
需求说明
需要合并两组数据:电影数据(List<Movie>)和分类数据(List<Genres>),仅当两者的id相同时进行关联。其中:
Movie类包含id(主键)、name字段Genres类包含id(外键)、name字段
示例输入数据
List<Movie> movies = new ArrayList<>(); movies.add(new Movie(1, "Titanic")); movies.add(new Movie(2, "Batman")); movies.add(new Movie(3, "Silence of the Lambs")); movies.add(new Movie(4, "1917")); movies.add(new Movie(5, "Fight Club")); movies.add(new Movie(6, "Inception")); movies.add(new Movie(7, "The Godfather")); movies.add(new Movie(8, "Peral Harbor")); List<Genres> genres = new ArrayList<>(); genres.add(new Genres(1, "Drama")); genres.add(new Genres(4, "Drama")); genres.add(new Genres(8, "Drama")); genres.add(new Genres(7, "Drama")); genres.add(new Genres(2, "Action")); genres.add(new Genres(5, "Action")); genres.add(new Genres(6, "SF")); genres.add(new Genres(3, "Thriller")); genres.add(new Genres(5, "Thriller")); genres.add(new Genres(5, "Crime")); genres.add(new Genres(16, "Comedy")); genres.add(new Genres(3, "Horror")); genres.add(new Genres(1, "Disaster")); genres.add(new Genres(7, "Noir")); genres.add(new Genres(1, "Romance"));
期望输出结果
[ {"id": 1, "name": "Titanic", "genres": ["Drama", "Disaster", "Romance"]}, {"id": 2, "name": "Batman", "genres": ["Action"]}, {"id": 3, "name": "Silence of the Lambs", "genres": ["Thriller", "Horror"]}, {"id": 4, "name": "1917", "genres": ["Drama"]}, {"id": 5, "name": "Fight Club", "genres": ["Action", "Thriller", "Crime"]}, {"id": 6, "name": "Inception", "genres": ["SF"]}, {"id": 7, "name": "The Godfather", "genres": ["Drama", "Noir"]}, {"id": 8, "name": "Peral Harbor", "genres": ["Drama"]} ]
Stream实现方案
步骤说明
- 预分组分类数据:先将
Genres列表按id分组,把同一id对应的所有分类名称收集到列表中,得到Map<Integer, List<String>>结构,避免后续多次遍历分类列表,提升效率。 - 关联电影与分类:遍历
Movie列表,对每个电影,从分组后的Map中获取对应的分类列表(若没有匹配的id则返回空列表),最后组装成包含分类列表的目标对象。
完整代码实现
首先定义基础实体类和结果DTO类:
// 电影实体类 class Movie { private Integer id; private String name; public Movie(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public String getName() { return name; } } // 分类实体类 class Genres { private Integer id; private String name; public Genres(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public String getName() { return name; } } // 结果DTO类,存储关联后的电影与分类信息 class MovieWithGenres { private Integer id; private String name; private List<String> genres; public MovieWithGenres(Integer id, String name, List<String> genres) { this.id = id; this.name = name; this.genres = genres; } // 重写toString方法,让输出匹配JSON格式 @Override public String toString() { return String.format("{\"id\": %d, \"name\": \"%s\", \"genres\": %s}", id, name, genres.toString().replaceAll("\\[", "\\[\"").replaceAll("\\]", "\"\\]").replaceAll(", ", "\", \"")); } }
然后是Stream处理逻辑:
public class MovieGenreMerge { public static void main(String[] args) { // 初始化示例数据 List<Movie> movies = new ArrayList<>(); movies.add(new Movie(1, "Titanic")); movies.add(new Movie(2, "Batman")); movies.add(new Movie(3, "Silence of the Lambs")); movies.add(new Movie(4, "1917")); movies.add(new Movie(5, "Fight Club")); movies.add(new Movie(6, "Inception")); movies.add(new Movie(7, "The Godfather")); movies.add(new Movie(8, "Peral Harbor")); List<Genres> genres = new ArrayList<>(); genres.add(new Genres(1, "Drama")); genres.add(new Genres(4, "Drama")); genres.add(new Genres(8, "Drama")); genres.add(new Genres(7, "Drama")); genres.add(new Genres(2, "Action")); genres.add(new Genres(5, "Action")); genres.add(new Genres(6, "SF")); genres.add(new Genres(3, "Thriller")); genres.add(new Genres(5, "Thriller")); genres.add(new Genres(5, "Crime")); genres.add(new Genres(16, "Comedy")); genres.add(new Genres(3, "Horror")); genres.add(new Genres(1, "Disaster")); genres.add(new Genres(7, "Noir")); genres.add(new Genres(1, "Romance")); // 1. 将分类数据按id分组,提取分类名称 Map<Integer, List<String>> genreMap = genres.stream() .collect(Collectors.groupingBy( Genres::getId, Collectors.mapping(Genres::getName, Collectors.toList()) )); // 2. 关联电影与分类,生成结果列表 List<MovieWithGenres> result = movies.stream() .map(movie -> new MovieWithGenres( movie.getId(), movie.getName(), genreMap.getOrDefault(movie.getId(), Collections.emptyList()) )) .collect(Collectors.toList()); // 输出结果 System.out.println("result: ["); result.forEach(item -> System.out.println(" " + item + ",")); System.out.println(" ]"); } }
代码说明
Collectors.groupingBy配合Collectors.mapping直接完成分类数据的分组与名称提取,简化后续处理。Map.getOrDefault确保无匹配分类时返回空列表,避免空指针异常。- 重写
toString方法让输出格式与期望的JSON结构一致,方便查看结果。
内容的提问来源于stack exchange,提问作者footlessbird
相关产品推荐
相关产品推荐

