【问题标题】:Java - Turn Object with List Variable into a List of ObjectsJava - 将带有列表变量的对象转换为对象列表
【发布时间】:2019-06-12 02:53:22
【问题描述】:

我的基础课是:

public class Student {
  public String name;
  public String className; // In real code I'd have a second object for return to the end user
  public List<String> classes; // Can be zero
}

我想把它弄平,这样我就可以返回类似的东西

[
  {
    "name":"joe",
    "class":"science"
  },
  {
    "name":"joe",
    "class":"math"
  },
]

为了简单起见,显然是一个愚蠢的例子。

我能够做到这一点的唯一方法是通过一些冗长的代码,例如:

List<Student> students = getStudents();
List<Student> outputStudents = new ArrayList<>();
students.forEach(student -> {
  if(student.getClasses().size() > 0) {
    student.getClasses().forEach(clazz -> {
      outputStudents.add(new Student(student.getName(), clazz));
    });
  } else {
    outputStudents.add(student);
  }
});

看看有没有办法简化这个,也许使用flapMap?

【问题讨论】:

  • 您是在问如何构建 JSON?
  • 另外class是一个关键字,所以你不能在这样的lambda中使用它
  • 这是 sudo 代码,所以我有点懒惰。我将 lombok 用于获取器/设置器。并且讨厌收集资源等。
  • 哦误读了这个问题。 Hateoas/HttpEntity 将为我处理对象-> json。所以我只需要以正确的方式组装对象。就像所有有趣的事情一样,我必须满足另一个系统对我如何发送它的需求。
  • 这段代码中有三个属性,但显示的输出中有两个。目前还不太清楚你想要什么。 classNameclasses 有何不同?

标签: java arrays java-stream flatmap


【解决方案1】:

是的,你应该可以这样做:

Student student = ?
List<Student> output = 
    student
        .getClasses()
        .stream()
        .map(clazz -> new Student(student.getName, student.getClassName, clazz))
        .collect(Collectors.toList());

对于单个学生。对于一群学生来说,这有点复杂:

(由于@nullpointer 评论中的观察而更新。谢谢!)

List<Student> listOfStudents = getStudents();
List<Student> outputStudents =
    listOfStudents
        .stream()
        .flatMap(student -> {
            List<String> classes = student.getClasses();
            if (classes.isEmpty()) return ImmutableList.of(student).stream();
            return classes.stream().map(clazz -> new Student(student.getName(), student.getClassName(), ImmutableList.of(clazz)));
        })
        .collect(Collectors.toList());

【讨论】:

  • 是的,我至少可以处理空值检查 =) 你的代码也对我有用。谢谢!我可能会进行性能比较,看看哪种方式更有趣
  • 如果 student 没有 classes (size =0),这不会像相关代码那样在输出列表中映射该学生。 @jwismar ...此外,答案中使用的构造函数与实际的类属性不匹配,如果它周围有一些自定义逻辑,则值得分享。
  • 这是一个很好的观点。感谢您指出!已更新。
【解决方案2】:

一种方法是根据条件划分Students 的当前列表(如果其中的类是否为空)

Map<Boolean, List<Student>> conditionalPartitioning = students.stream()
        .collect(Collectors.partitioningBy(student -> student.getClasses().isEmpty(), Collectors.toList()));

然后进一步使用此分区到flatMap 到一个新学生列表,因为这些学生在其中有课程,concatenate 他们与另一个分区最终收集到结果中:

List<Student> result = Stream.concat(
        conditionalPartitioning.get(Boolean.FALSE).stream() // classes as a list
                .flatMap(student -> student.getClasses() // flatmap based on each class
                        .stream().map(clazz -> new Student(student.getName(), clazz))),
        conditionalPartitioning.get(Boolean.TRUE).stream()) // with classes.size = 0
        .collect(Collectors.toList());

【讨论】:

  • 条件分区是我见过的最酷的东西之一!我希望我能接受这两个答案,因为它们都以不同的方式解决问题。
  • @canpan14 没关系,答案不仅适用于预先提出问题的人,这个(答案)也有望帮助其他人登陆问题链接。最后,消费者可以评估如果有多种方法可供他们使用,他们将从中受益。 :)
猜你喜欢
  • 1970-01-01
  • 2018-01-24
  • 2015-04-14
  • 2019-06-09
  • 2013-12-02
  • 1970-01-01
  • 2021-10-01
  • 2013-08-14
相关资源
最近更新 更多