【问题标题】:Grouping objects to list using lambda使用 lambda 将对象分组以列出
【发布时间】:2022-01-04 12:58:37
【问题描述】:

我遇到了问题,因为我的选择返回了几行结果,因为 Options 对象有几个不同的选项,我需要在 java 中对这个结果进行分组。

我的父类是 QuestionEventDTO:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class QuestionEventDTO {
    
    public Long id;
    public QuestionDTO question;
    public List<QuestionDTO> questions;

}

我有女儿班:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class QuestionDTO {
    
    public Long id;
    public OptionDTO option;
    public List<OptionDTO> options;

}

我有孙女班:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class OptionDTO {
    
    public Long id;
    public String description;

}

点击程序后,我设置了响应字段:

public class QuestionEventMapper implements RowMapper<QuestionEventDTO> {

    @Override
    public QuestionEventDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
        QuestionEventDTO dto = new QuestionEventDTO();
        dto.setId(rs.getLong(1));
        dto.setQuestion(new QuestionDTO(rs.getLong(2), new QuestionOptionDTO(rs.getLong(3), rs.getString(4)), null));
        
        return dto;
    }

}
QuestionEventDTO [id=1, question= QuestionDTO [id=1, option= OptionDTO [id=1, description="Are you Dev?"], options = []], questions =[]]
QuestionEventDTO [id=1, question= QuestionDTO [id=1, option= OptionDTO [id=2, description="What's rating?"], options = []], questions =[]]
QuestionEventDTO [id=2, question= QuestionDTO [id=2, option= OptionDTO [id=3, description="What's your dog's name?"], options = []], questions =[]]
QuestionEventDTO [id=2, question= QuestionDTO [id=2, option= OptionDTO [id=4, description="Are you Dev?"], options = []], questions =[]]

但我希望它保持这样:

QuestionEventDTO [id=1, question= null, questions = QuestionDTO [id=1, option= null, options = [OptionDTO [id=1, description="Are you Dev?"], OptionDTO [id=2, description="What's rating?"]]]]
QuestionEventDTO [id=2, question= null, questions = QuestionDTO [id=2, option= null, options = [OptionDTO [id=3, description="What's your dog's name?"], OptionDTO [id=4, description="Are you Dev?"]]]]

我在 lambda 方面没有太多经验,我想解决这个问题,有人可以帮助我吗?

【问题讨论】:

  • 不要强迫自己写 lambda,用普通代码加上 for 循环就可以了,以后我们可以转成 lambda。
  • @huy 所以我尝试在没有 lambda 的情况下这样做,但它没有工作......
  • 我没有看到您的代码从选择转换为预期数据。
  • 你的选择怎么样?
  • 这是我执行的程序,当我设置值时,我设置了我要在问题中发布的方式

标签: java lambda java-stream


【解决方案1】:

我会试一试的。

警告 |请注意,这只是一个 POC,而不是可读性好的代码。

您需要的是一种方法,它接受 List&lt;QuestionEventDTO&gt; 并将其转换为另一个 List&lt;QuestionEventDTO&gt;。

可以在 map-methods 中使用流和嵌套流来实现。

这是该流将采取的步骤:


  1. 按QuestionEventDTO 的ID 将QuestionDTO 分组
    • 输入:List&lt;QuestionEventDTO&gt;
    • 输出:Map&lt;Long, List&lt;QuestionEventDTO&gt;&gt;
  2. 将分组列表转换为Map&lt;Long, List&lt;QuestionDTO&gt;
    • 输入:Map&lt;Long, List&lt;QuestionEventDTO&gt;&gt;
    • 输出:Map&lt;Long, Map&lt;Long, List&lt;QuestionDTO&gt;&gt;&gt;
  3. 将分组的QuestionDTO 转换为Map&lt;Long, OptionDTO&gt;
    • 输入:Map&lt;Long, Map&lt;Long, List&lt;QuestionDTO&gt;&gt;&gt;
    • 输出:Map&lt;Long, Map&lt;Long, Map&lt;Long, OptionDTO&gt;&gt;&gt;

  1. 将分组的对象转换为填充列表的新QuestionEventDTO。

下面是代码的样子(大量使用Collectors.groupingBy 和Collectors.toMap):

private static List<QuestionEventDTO> transform(List<QuestionEventDTO> events) {
  //Step1
  Map<Long, List<QuestionEventDTO>> groupedByQuestionEventId = events.stream()
      .collect(Collectors.groupingBy(QuestionEventDTO::getId));
  
  //Step 2
  Map<Long, Map<Long, List<QuestionDTO>>> alsoGroupedQuestionID = groupedByQuestionEventId
      .entrySet().stream()
      .collect(Collectors.toMap(Map.Entry::getKey,
          e -> e.getValue().stream()
              .map(v -> v.getQuestion())
              .collect(Collectors.groupingBy(QuestionDTO::getId)))
      );

  //Step 3
  Map<Long, Map<Long, Map<Long, OptionDTO>>> alsoGroupedByOptionID = alsoGroupedQuestionID
      .entrySet().stream()
      .collect(Collectors.toMap(Map.Entry::getKey,
          e -> e.getValue()
              .entrySet().stream()
              .collect(Collectors.toMap(Map.Entry::getKey,
                  v -> v.getValue().stream()
                      .map(QuestionDTO::getOption)
                      .collect(Collectors.toMap(OptionDTO::getId, t -> t))))));

  //Step 4
  List<QuestionEventDTO> transformedBack = alsoGroupedByOptionID.entrySet().stream()
      .map(e -> {
        QuestionEventDTO eventDTO = new QuestionEventDTO();
        eventDTO.setId(e.getKey());

        List<QuestionDTO> questions = e.getValue().entrySet().stream()
            .map(q -> {
              QuestionDTO questionDTO = new QuestionDTO();
              questionDTO.setId(q.getKey());
              questionDTO.setOptions(new ArrayList<>(q.getValue().values()));
              return questionDTO;
            }).collect(Collectors.toList());

        eventDTO.setQuestions(questions);
        return eventDTO;
      })
      .collect(Collectors.toList());

  return transformedBack;
}

当然你不需要每个步骤的变量,你也可以将步骤 2 和 3 结合起来。然后代码看起来像这样(不是很可读):

private static List<QuestionEventDTO> transformShorter(List<QuestionEventDTO> events) {
  return events.stream()
      .collect(Collectors.groupingBy(QuestionEventDTO::getId))
      .entrySet().stream()
      .collect(Collectors.toMap(Map.Entry::getKey,
          e -> e.getValue().stream()
              .map(QuestionEventDTO::getQuestion)
              .collect(Collectors.groupingBy(QuestionDTO::getId))
              .entrySet().stream()
              .collect(Collectors.toMap(Map.Entry::getKey, 
                  q -> q.getValue().stream()
                      .map(QuestionDTO::getOption)
                      .collect(Collectors.toList()))))
      )
      .entrySet().stream()
      .map(e -> {
        QuestionEventDTO eventDTO = new QuestionEventDTO();
        eventDTO.setId(e.getKey());

        List<QuestionDTO> questions = e.getValue().entrySet().stream()
            .map(q -> {
              QuestionDTO questionDTO = new QuestionDTO();
              questionDTO.setId(q.getKey());
              questionDTO.setOptions(q.getValue());
              return questionDTO;
            }).collect(Collectors.toList());

        eventDTO.setQuestions(questions);
        return eventDTO;
      })
      .collect(Collectors.toList());
}

【讨论】:

    猜你喜欢
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    相关资源
    最近更新 更多