Java收集器:将对象列表分组为具有计算值的其他对象列表

时间:2018-12-09 08:37:30

标签: java java-8 java-stream collectors

我最近开始使用Java 8及其Stream API,最近又使用了Collectors API,我发现它有潜力进行许多转换以流式传输,但是我遇到的一种情况是我没有确保在Java 8中可能甚至根本没有。我有两节课:

public class ClassA{
    public int group
    public int id
    public String title
    public String description
    public String keyword
    public String specialValue
}

public class ClassB{
    public String newTitle
    public String joinedDescriptions
}

我想知道是否有可能从ClassA对象的列表中生成一组ClassB对象的列表,这些列表具有从ClassA的字段中计算出的值。具体来说:

  • 通过组和ID的组合对ClassA进行分组
  • 当关键字= 1时,分组的ClassB实例将具有newTitle =标题,而当关键字= 2时将具有newTitle = specialValue
  • 最后是joinDescriptions,是来自ClassA实例分组的所有描述的串联。

我知道可以使用收集器的groupingBy通过classA-> String.valueOf(classA.group)+ String.valueOf(classA.id)或类似的lambda对ClassA实例进行分组,但是我不会不知道要为每个分组实例获得其他计算值。

我希望对它的解释足够充分。

1 个答案:

答案 0 :(得分:0)

下面是要采取的步骤;类似于@Joakim Danielson在评论中提到的内容:

按照您在帖子中提到的方式对源列表进行分组,然后在ClassB中添加一个包含ClassA列表的构造函数,然后执行您在设置标题并加入说明:

所以这将是您的流管道:

List<ClassB> result = source.stream()
                .collect(groupingBy(s -> s.getGroup() + "" + s.getId())) // Map<String, List<ClassA>>
                .values()  // Collection<List<ClassA>>
                .stream() // Stream<List<ClassA>>
                .map(ClassB::new) // Stream<ClassB>
                .collect(Collectors.toList()); //List<ClassB>>

,您将需要在ClassB中定义一个构造函数:

public ClassB(List<ClassA> source) {
        ClassA item = source.get(0);
        if(“1”.equals(item.getKeyword())
             this.newtitle = item.getTitle();
        else if(“2”.equals(item.getKeyword())
             this.newtitle = “specialValue”; // or make a call to a method to compute the value
        this.joinedDescriptions = String.join(“, “, source.stream().map(ClassA::getDescription).collect(toList()));
}