如何使用 JAVA 8 对不同类型列表的字段进行分组?

How to group fields of different type lists using JAVA 8?

这里是博士生,也是学校的老师。 这两个对象之间的共同点是它们的名称。 所以我用他们的名字过滤数据。 根据我在 MyMain class 中编写的代码,我能够过滤公共记录并获取学生数据。 但我也想要 Student 和 Teacher 的详细信息,并在 StudentTeacherMapper 中设置。请帮助我设置 StudentTeacherMapper class 中的字段。谢谢。

@Getter
@Setter
public class PHDStudent {
                
    private int studentId;
    private String studentName;
    private String grade;
    private int rank;
                
}
       
@Getter
@Setter
public class SCHLTeacher {
            
    private int teacherId;
    private String teacherName;
    private String place;
    private Long Salary;                
}
    
@Getter
@Setter
public class StudentTeacherMapper {
        
    private int teacherId;
    private String teacherName;
    private String place;
    private Long Salary;
    private int studentId;
    private String studentName;
    private String grade;
    private int rank;
    
}


public class MyMain {
    
    public static void main(String[] args) {
        
        List<SCHLTeacher> teachList = new ArrayList<>();
        List<PHDStudent> studList = new ArrayList<>();

        mapStudentTeacherData(teachList, studList);
        
        List<PHDStudent> studentList = teachList.stream().flatMap(
                teach -> studList.stream().filter(predicate -> predicate.getStudentName().equals(teach.getTeacherName())))
                .collect(Collectors.toList());
        
        StudentTeacherMapper mapper = new StudentTeacherMapper();
        //set data in mapper
        

    }

    private static void mapStudentTeacherData(List<SCHLTeacher> teachList, List<PHDStudent> studList) {
        SCHLTeacher teach1 = new SCHLTeacher();
        teach1.setPlace("Mumbai");
        teach1.setSalary(100000L);
        teach1.setTeacherId(11);
        teach1.setTeacherName("Ms.Grace444");
        SCHLTeacher teach2 = new SCHLTeacher();
        teach2.setPlace("Delhi");
        teach2.setSalary(160000L);
        teach2.setTeacherId(22);
        teach2.setTeacherName("Mr.Paul123");
        
        teachList.add(teach1);
        teachList.add(teach2);

        PHDStudent stud1 = new PHDStudent();
        stud1.setGrade("A");
        stud1.setRank(1);
        stud1.setStudentId(11);
        stud1.setStudentName("Ms.Grace444");
        PHDStudent stud2 = new PHDStudent();
        stud2.setGrade("C");
        stud2.setRank(44);
        stud2.setStudentId(22);
        stud2.setStudentName("Mr.Paul123");
        PHDStudent stud3 = new PHDStudent();
        stud3.setGrade("B");
        stud3.setRank(12);
        stud3.setStudentId(45);
        stud3.setStudentName("Mr.X22");
        
        studList.add(stud1);
        studList.add(stud2);
        studList.add(stud3);
    }

}

StudentTeacherMapper class 中定义一个 constructor 以容纳 PHDStudentSCHLTeacher class 如下所示:

public StudentTeacherMapper(PHDStudent student, SCHLTeacher teacher) {
    if (teacher != null) {
        this.teacherId = teacher.getTeacherId();
        this.teacherName = teacher.getTeacherName();
        this.place = teacher.getPlace();
        this.salary = teacher.getSalary();
    }
    if (student != null) {
        this.studentId = student.getStudentId();
        this.studentName = student.getStudentName();
        this.grade = student.getGrade();
        this.rank = student.getRank();
    }
}

mainclass中,在mapStudentTeacherData(teachList, studList)之后,进行如下操作:

List<StudentTeacherMapper> mappers = new ArrayList<>();

teachList.forEach(x -> {
    List<PHDStudent> students = studList
            .stream()
            .filter(y -> x.getTeacherName()
                    .equals(y.getStudentName()))
            .collect(Collectors.toList());
    if(students.size() > 0) {
        students.stream().forEach(z -> {
            StudentTeacherMapper mapper = new StudentTeacherMapper(z,x);
            mappers.add(mapper);
        });
    }
});

// do what you want with the mappers

创建构造函数:

public StudentTeacherMapper(SCHLTeacher teacher, PHDStudent student){
    StudentTeacherMapper mapper = new StudentTeacherMapper();
    mapper.setTeacherId(teacher.getTeacherId());
    mapper.setPlace(teacher.getPlace());
    mapper.setTeacherName(teacher.getTeacherName());
    mapper.setSalary(teacher.getSalary());
    mapper.setStudentName(student.getStudentName());
    mapper.setStudentId(student.getStudentId());
    mapper.setGrade(student.getGrade());
    mapper.setRank(student.getRank());
}

并使用 Stream API:

收集映射器
List<StudentTeacherMapper> mappers = teachList
    .stream()
    .flatMap(teach ->
         studList
             .stream()
             .filter(student -> student.getStudentName().equals(teach.getTeacherName()))
             .findFirst()
             .map(student -> Stream.of(new StudentTeacherMapper(teach, student)))
             .orElseGet(Stream::empty)
    ).collect(Collectors.toList());

首先要做的是在 StudentTeacherMapper class.

中放置两个构造函数
  • 第一个是给学生和老师的
  • 第二个仅适用于学生(您的示例表明您有一个学生超集)。这个有教师数据的默认值。 getter 和 setter 未显示。
class StudentTeacherMapper {
    private int teacherId;
    private String teacherName;
    private String place;
    private long Salary = 0L;
    private int studentId;
    private String studentName;
    private String grade;
    private int rank;
    
    public StudentTeacherMapper(int teacherId, String teacherName,
            String place, long salary, int studentId,
            String studentName, String grade, int rank) {
        
        this.teacherId = teacherId;
        this.teacherName = teacherName;
        this.place = place;
        Salary = salary;
        this.studentId = studentId;
        this.studentName = studentName;
        this.grade = grade;
        this.rank = rank;
    }

    public StudentTeacherMapper(int studentId, String studentName,
            String grade, int rank) {
        this(-1, "No teacher assigned", "No place defined", 0L, studentId, studentName,
                grade, rank);
    }   
}

接下来,制作一张教师地图,以便将他们与学生联系起来。假设没有重复的教师姓名(否则会导致其他并发症)。一种想法是拥有一个适用于教师和学生的唯一 ID。

Map<String, SCHLTeacher> teachers = teachList.stream()
                .collect(Collectors.toMap(SCHLTeacher::getName, t->t));

现在用那个地图来协调两者。调用的构造函数取决于老师的存在。结果在stList

        
List<StudentTeacherMapper> stList =
        studList.stream().map(s -> {
            SCHLTeacher t = teachers.get(s.getStudentName());
            return t != null ?
                    new StudentTeacherMapper(t.getTeacherId(),
                            t.getTeacherName(), t.getPlace(),
                            t.getSalary(), s.getStudentId(),
                            s.getStudentName(), s.getGrade(),
                            s.getRank()) :
                    new StudentTeacherMapper(s.getStudentId(),
                            s.getStudentName(), s.getGrade(),
                            s.getRank());
        }).toList(); // or collect(Collectors.toList());

一些建议。

  • 正如我之前提到的,一个学生和教师通用的 ID 会很有用。
  • 为什么在映射器中有两次名称 class。看来只有一个是必须的,因为它是用来联系学生和老师的名字。