Java中如何合并ArrayList内同名Course对象并聚合学生数组
同名课程合并实现方案
需求说明
现有存储Course类型对象的ArrayList集合,每个Course对象包含两个属性:
- 课程名称
name - 学生数组
students
需要合并所有同名课程,最终集合中每个课程名称仅保留一条记录,对应学生数组包含该课程下的全部学生。
初始集合示例
ArrayList<Course> courses = { Course("math", {student1, student2}), Course("art", {student3, student4}), Course("math", {student5, student6}) };
合并后期望结果
ArrayList<Course> courses = { Course("math", {student1, student2, student5, student6}), Course("art", {student3, student4}) };
基础类定义
public class Course { String name; String[] students; public Course(String name, String[] students) { this.name = name; this.students = students; } } public class Student { String name; public Student(String name) { this.name = name; } }
实现思路
用LinkedHashMap做中间聚合容器是最简便高效的方案:
- Key存储课程名称,保证同名课程只会对应一个聚合节点
- Value存储该课程下聚合的所有学生,用
LinkedHashMap还能保留课程在原集合中首次出现的顺序,避免打乱原有排序 - 一次遍历原集合即可完成所有数据聚合,最后遍历Map把结果转回
ArrayList<Course>即可,时间复杂度O(n),效率远高于嵌套循环查重的实现
完整实现代码
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class CourseUtils { public static ArrayList<Course> mergeSameNameCourses(List<Course> originList) { Map<String, List<String>> courseAggregate = new LinkedHashMap<>(); // 遍历原集合做聚合 for (Course course : originList) { // 首次遇到该课程时初始化学生列表 courseAggregate.computeIfAbsent(course.name, key -> new ArrayList<>()); // 将当前课程的所有学生加入聚合列表 courseAggregate.get(course.name).addAll(Arrays.asList(course.students)); } // 聚合结果转成目标Course集合 ArrayList<Course> result = new ArrayList<>(); for (Map.Entry<String, List<String>> entry : courseAggregate.entrySet()) { String courseName = entry.getKey(); String[] mergedStudents = entry.getValue().toArray(new String[0]); result.add(new Course(courseName, mergedStudents)); } return result; } }
可选调整
- 如果业务要求同一个课程下学生不能重复,只需要把存储学生的
ArrayList替换成LinkedHashSet即可,自动去重的同时还能保留学生首次出现的顺序,其余逻辑不需要改动 - 如果实际业务中
Course类的students属性是Student[]类型而非示例中的String[],只需要把Map的泛型对应调整为Map<String, List<Student>>,添加学生、转数组的逻辑同步适配即可,整体实现思路完全一致
内容的提问来源于stack exchange,提问作者tole_gom
相关产品推荐
相关产品推荐

