探讨一种 Java 实现分组的方法

381 阅读2分钟

我这里实现了一种分组方式,但是始终感觉太过暴力,有没有大佬提供一种更优雅的方式来进行 Java 对象 List 的分组呢?

需求:

原数据格式

[
    {"stuNum":"001","stuName":"Tom","course":"语文","score":65},
    {"stuNum":"001","stuName":"Tom","course":"数学","score":80},
    {"stuNum":"001","stuName":"Tom","course":"英语","score":88},
    {"stuNum":"002","stuName":"Mike","course":"语文","score":70},
    {"stuNum":"002","stuName":"Mike","course":"数学","score":85},
    {"stuNum":"002","stuName":"Mike","course":"英语","score":90},
    {"stuNum":"003","stuName":"Lucy","course":"语文","score":70},
    {"stuNum":"003","stuName":"Lucy","course":"数学","score":60}
]

目标数据格式:

[
    {"stuNum":"001","stuName":"Tom","courseScoreList":[
        {"course":"语文","score":65},
        {"course":"数学","score":80},
        {"course":"英语","score":88}]
    },
    {"stuNum":"002","stuName":"Mike","courseScoreList":[
        {"course":"语文","score":70},
        {"course":"数学","score":85},
        {"course":"英语","score":90}]
    },
    {"stuNum":"003","stuName":"Lucy","courseScoreList":[
        {"course":"语文","score":70},
        {"course":"数学","score":60}]
    }
]

我把代码放在这里大家探讨一下(可复制到 IDE 中执行查看效果,依赖包自行引入):

public class GroupBySomeProperty {

    @Test
    public void groupByTest() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        List<StudentScore> scoreList = getTestData();
        List<StudentGrade> gradeList = groupByStu(scoreList);
        System.out.println(objectMapper.writeValueAsString(scoreList));
        System.out.println(objectMapper.writeValueAsString(gradeList));
    }

    private List<StudentGrade> groupByStu(List<StudentScore> scoreList) {
        List<StudentGrade> gradeList = scoreList.parallelStream().filter(distinctByKey(StudentScore::getStuNum)).map(score -> new StudentGrade() {{
            setStuNum(score.getStuNum());
            setStuName(score.getStuName());
        }}).collect(Collectors.toList());
        for (StudentGrade grade : gradeList) {
            List<CourseScore> tempCourseScoreList = scoreList.stream()
                    .filter(score -> score.getStuNum().equals(grade.stuNum))
                    .map(score -> new CourseScore() {{
                        setCourse(score.getCourse());
                        setScore(score.getScore());
                    }}).collect(Collectors.toList());
            grade.setCourseScoreList(tempCourseScoreList);

        }
        return gradeList;
    }

    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    private List<StudentScore> getTestData() {
        StudentScore student1 = new StudentScore() {{
            setStuNum("001");
            setStuName("Tom");
            setCourse("语文");
            setScore(65);
        }};
        StudentScore student2 = new StudentScore() {{
            setStuNum("001");
            setStuName("Tom");
            setCourse("数学");
            setScore(80);
        }};
        StudentScore student3 = new StudentScore() {{
            setStuNum("001");
            setStuName("Tom");
            setCourse("英语");
            setScore(88);
        }};
        StudentScore student4 = new StudentScore() {{
            setStuNum("002");
            setStuName("Mike");
            setCourse("语文");
            setScore(70);
        }};
        StudentScore student5 = new StudentScore() {{
            setStuNum("002");
            setStuName("Mike");
            setCourse("数学");
            setScore(85);
        }};
        StudentScore student6 = new StudentScore() {{
            setStuNum("002");
            setStuName("Mike");
            setCourse("英语");
            setScore(90);
        }};
        StudentScore student7 = new StudentScore() {{
            setStuNum("003");
            setStuName("Lucy");
            setCourse("语文");
            setScore(70);
        }};
        StudentScore student8 = new StudentScore() {{
            setStuNum("003");
            setStuName("Lucy");
            setCourse("数学");
            setScore(60);
        }};

        return new ArrayList<StudentScore>() {{
            add(student1);
            add(student2);
            add(student3);
            add(student4);
            add(student5);
            add(student6);
            add(student7);
            add(student8);
        }};
    }

    private class StudentGrade {
        private String stuNum;
        private String stuName;
        private List<CourseScore> courseScoreList;

        public String getStuNum() {
            return stuNum;
        }

        public void setStuNum(String stuNum) {
            this.stuNum = stuNum;
        }

        public String getStuName() {
            return stuName;
        }

        public void setStuName(String stuName) {
            this.stuName = stuName;
        }

        public List<CourseScore> getCourseScoreList() {
            return courseScoreList;
        }

        public void setCourseScoreList(List<CourseScore> courseScoreList) {
            this.courseScoreList = courseScoreList;
        }
    }

    private class CourseScore {
        private String course;
        private Integer score;

        public String getCourse() {
            return course;
        }

        public void setCourse(String course) {
            this.course = course;
        }

        public Integer getScore() {
            return score;
        }

        public void setScore(Integer score) {
            this.score = score;
        }
    }

    private class StudentScore {
        private String stuNum;
        private String stuName;
        private String course;
        private Integer score;

        public String getStuNum() {
            return stuNum;
        }

        public void setStuNum(String stuNum) {
            this.stuNum = stuNum;
        }

        public String getStuName() {
            return stuName;
        }

        public void setStuName(String stuName) {
            this.stuName = stuName;
        }

        public String getCourse() {
            return course;
        }

        public void setCourse(String course) {
            this.course = course;
        }

        public Integer getScore() {
            return score;
        }

        public void setScore(Integer score) {
            this.score = score;
        }
    }
}