如何使用 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
以容纳 PHDStudent
和 SCHLTeacher
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();
}
}
在main
class中,在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。看来只有一个是必须的,因为它是用来联系学生和老师的名字。
这里是博士生,也是学校的老师。 这两个对象之间的共同点是它们的名称。 所以我用他们的名字过滤数据。 根据我在 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
以容纳 PHDStudent
和 SCHLTeacher
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();
}
}
在main
class中,在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。看来只有一个是必须的,因为它是用来联系学生和老师的名字。