Java 8 Group Objects由一个公共子对象组成

时间:2017-12-27 20:50:53

标签: java

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

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

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

enter image description here

目标:

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

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

Java 8有一些流/过滤功能,它们会在这里有用吗?或者我是否需要转到数据库并重构我的SQL查询?

1 个答案:

答案 0 :(得分:1)

您可以按照从集合元素计算的值对项目进行分组。例如,要按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中执行此操作)减少产生相同类型的步骤)
相关问题