将平面列表元素转换为java中的嵌套集合

时间:2017-11-09 06:59:04

标签: java collections group-by

我有一个元素列表,我需要按此列表类型的某些元素进行分组,并将其转换为嵌套集合。这就是我的意思 -

请考虑以下内容 -

class StudentA {
    private String name;
    private int age;
    private int subjectId;
    private String subjectName;
}

class StudentB {
    private String name;
    private int age;
    List<Subject> subject;
}

class Subject {
    private int subjectId;
    private String subjectName;
}

我有List<StudentA>作为我的输入。但是在这个列表中,每个学生可以有多个科目,因此学生信息是重复的(例如:[new StudentA("A",22,1,"X"), new StudentA("A",22,2,"Y"), new StudentA("B",24,1,"X") ]等等)。 这不是一个好的表示,我需要以下格式的数据 -

List<StudentB>

请注意,StudentB将Subject列为元素。

这是我的想法,但不相信,

  • 简单的旧迭代方式,我迭代遍历每个元素 原始清单并构建我需要的东西
  • 我也看过java8 流api,其中groupby收集的数据看起来很有希望, 但我似乎无法从列表中的StudentA类型转换为我的 学生B类型

执行此操作的有效方法是什么?非常感谢!

1 个答案:

答案 0 :(得分:3)

如果您按名称对StudentA的实例进行分组,则会获得Map<String,List<StudentA>>。然后,您可以流式传输此地图的值并将其转换为StudentB的实例:

List<StudentB> bList =
    aList.stream() // Stream<StudentA>
         .collect(Collectors.groupingBy(StudentA::getName)) // Map<String,List<StudentA>>
         .values() // Collection<List<StudentA>>
         .stream() // Stream<List<StudentA>>
         .map(list -> {
             StudentB b = new StudentB();
             b.setName(list.get(0).getName());
             b.setAge(list.get(0).getAge());
             list.forEach(a -> b.addSubject(new Subject(a.getSubjectID(),a.getSubjectName())));
             return b;
         }) // Stream<StudentB>
         .collect(Collectors.toList());

我冒昧地假设存在一些方法名称和构造函数。

此解决方案的缺点是可能为同一Subject创建多个Subject个实例。如果您创建的Map<Integer,Subject>包含由其ID标记的Subject,并且只有在{{1}中尚未包含所需主题ID的情况下才创建新Subject,则可以避免这种情况}}