【问题标题】:Use lambda to group an object within a list according to the Id of the list使用 lambda 根据列表的 Id 对列表中的对象进行分组
【发布时间】:2022-01-04 05:04:30
【问题描述】:

晚安,我需要一些帮助来使用 Java 8 (lambda) 对对象列表进行分组

我有我的实体 QuestionEventDTO

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

}

当我咨询银行时,我得到了这样的外向回复:

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

但是,请注意 EventQuestion_id 是重复的,只有对象 QuestionDto 具有不同的 id。我想将 QuestionsDto 分组到一个 QuestionEvent 中,如下所示:

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

有人可以帮助我使用 lambda 找到一个好的解决方案吗?它是快速和高效的吗?谢谢。

【问题讨论】:

    标签: java lambda java-8


    【解决方案1】:

    您可以尝试像这样添加注释 @EqualsAndHashCode(exclude = {"question", "questions"})

    【讨论】:

      【解决方案2】:

      我认为这不是最好的方法,但我正在分享你想要的结果。

      allList.stream()
                  .collect(Collectors.groupingBy(QuestionEventDTO::getId))
                  .entrySet()
                  .stream()
                  .map(e -> {
                      QuestionEventDTO newInstance = new QuestionEventDTO();
                      newInstance.setId(e.getKey());
                      newInstance.setQuestions(e.getValue().stream().map(v -> v.getQuestion()).collect(Collectors.toList()));
                      return newInstance;
                  }).collect(Collectors.toList());
      

      【讨论】:

        【解决方案3】:

        这里需要将QuestionEventDTO 重新映射到新实例,并将question 字段设置为null,并填充列表。

        这可以使用带有合并功能的Collectors.toMap 来实现(和Supplier&lt;Map&gt; 提供LinkedHashMap 并保持插入顺序):

        List<QuestionEventDto> questionEvents; // input list
        List<QuestionEventDto> groupedById = new ArrayList<>(questionEvents
            .stream() // Stream<QuestionEventDto>
            .collect(Collectors.toMap(
                QuestionEventDto::getId, // key
                qe -> new QuestionEventDto(
                    qe.getId(), null, new ArrayList(Arrays.asList(qe.getQuestion()))
                ), // use all-args constructor
                (qe1, qe2) -> { 
                    qe1.getQuestions().addAll(qe2.getQuestions()); 
                    return qe1;
                },
                LinkedHashMap::new // keep insertion order
            )) // Map<Long, QuestionEventDto> created
            .values() // Collection<QuestionEventDto>
        ); // convert to ArrayList<QuestionEventDto>
        

        另一种解决方案可能是使用Collectors.groupingBy + Collectors.mapping:

        List<QuestionEventDto> questionEvents; // input list
        List<QuestionEventDto> groupedById = questionEvents
            .stream() 
            .collect(Collectors.groupingBy(
                QuestionEventDto::getId, // key
                LinkedHashMap::new,
                Collectors.mapping(
                    QuestionEventDto::getQuestion, Collectors.toList()
                ) // value - List<QuestionDto>
            ))
            .entrySet()
            .stream() // Stream<Map.Entry<Long, List<QuestionDto>>>
            .map(e -> new QuestionEventDto(e.getKey(), null, e.getValue()))
            .collect(Collectors.toList());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-02-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-06
          相关资源
          最近更新 更多