繁体   English   中英

Java 8 Group Objects通过一个公共子对象

[英]Java 8 Group Objects by a common sub-object

假设我有一个来自数据库的对象列表,格式如下

public class DBEvent {
    private String guiEventId;
    private String guiEventColor;
    private int questionId;
    private Date date;
    // + Getters/setters...
}

List<DBEvent>保存以下内容,并重复一些表格数据。 我需要按照相同的GuiEventId / GuiEventColor对所有条目进行分组,并拆分不同的QuestionId / Date。 这可以是一个新的对象列表。

在此处输入图片说明

目标:

public class NewEvent {
   private String guiEventId;
   private String guiEventColor;
   private Date date1;
   private Date date2;
}

换句话说,我需要捕获不同的Date(每对行1/2),同时保持其余信息相同,并将其作为对象。

Java 8具有一些流/过滤功能,它们在这里有帮助吗? 还是我需要去数据库并重组我的SQL查询?

您可以按从集合元素计算出的值对项目进行分组。 例如,要通过guiEventId对事件进行guiEventId ,可以调用:

List<DBEvent> events = ...//get events
Map<String, List<DBEvent>> groupedEvents = 
    events.stream().collect(Collectors.groupingBy(event -> event.getGuiEventId()));

这将生成一个映射,其中所有遇到的事件ID都映射到相应事件对象的列表。 如果您确定事件ID和颜色成对出现,那么将颜色包括在分组键中是多余的(尽管更改起来很容易)。

现在,对于给定的事件对组,您要做的就是将任何2元素列表的列表转换为单个元素。 为此,您可以将值列表转换为新类型的事件:

//define a function that takes a list of events and produces a new event:
private NewEvent createNewEvent(List<DBEvent> events) {
    NewEvent evt = new NewEvent();
    evt.setGuiEventId(events.get(0).getGuiEventId());
    evt.setGuiEventColor(events.get(0).getGuiEventColor());
    evt.setDate1(events.get(0).getDate());
    evt.setDate2(events.get(1).getDate());

    return evt;
}

现在,您可以将db事件列表映射的值集合中的值映射到NewEvent

List<NewEvent> newEvents = 
    groupedEvents.values().stream().map(eventList -> createNewEvent(eventList))
    .collect(Collectors.toList());

应注意以下几点:

  • 我假设您将不可避免地获得任何给定ID的一对事件。 如果不能保证,您可能需要验证或更改逻辑以避免错误或索引超出范围的错误
  • 如果每个事件ID有多个条目,则必须使用Stream.reduce来成对合并到一个新事件中(但随后必须分2个步骤进行操作,因为reduce产生的是同一类型)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM