我正在尝试找出处理以下场景的最佳方法。
我有一个按时间戳分组的数据库中发生的事件地图:
[2016-04-01 00:00:00, [event1, event2, event 3]]
[2016-02-01 00:00:00, [event5, event6]]
[2016-01-01 00:00:00, [event7, event8, event9, event10]]
我想在tableview中显示这些数据,每个事件时间戳只有一行。但是,事件中的某些值可能会重复。
例如:
事件定义是
class Event () {
LocalDateTime timestamp
String eventName
String eventDescription
}
我当时想要扁平化到这样的结构
class DisplayEvent () {
LocalDateTime timestamp
Collection<String> eventName
Collection<String> eventDescription
}
因此,在转换原始地图后,我留下以下列表:
displayEvent1
displayEvent2
displayEvent3
其中每个显示事件都包含原始事件的键,但是包含所有可变数据的数组。
我按如下方式创建了地图:
Map<LocalDateTime, List<Event>> eventsByTimestamp =
events
.stream()
.collect(Collectors.groupingBy(ev -> ev.timestampProperty().get()));
希望这是有道理的。
答案 0 :(得分:1)
在我看来,最好的方法取决于你的任务细节。
更通用的方法是类Event
:
public class Event
{
LocalDateTime timestamp;
String eventName;
String eventDescription;
}
然后,您可以按时间戳优雅地创建分组:
event.
stream().
collect(groupingBy(Event::getTimeStamp));
这当然不是那么有效,并且适用于较少的事件。因此,您可以考虑在从数据库中提取事件时对事件进行分组,例如:
public class EventRepository
{
Map<LocalDateTime, List<Event>> getAllEventsGroupedByTime();
}
在getAllEventsGroupedByTime
中,您将实例化事件对象并将它们放在相应的组中,而不在另一个应用程序层中重复此计算。
替代方法是这样的:
public class Event
{
String eventName;
String eventDescription;
}
public class EventGroup
{
LocalDateTime timestamp;
List<Event> events;
}
public class EventGroupRepository
{
List<EventGroups> getEventGroups();
}
老实说,我发现第二个解决方案没有什么好处(例如,一些对象引用不受影响)。所以我会选择no.1并在从DB中提取它们时对它们进行分组,特别是如果事件的数量不是那么大的话。这似乎更性感,因为事件时间自然属于事件。
<强>更新强>
好吧,您似乎希望使用很酷的java 8流将所有事件转换为显示事件的集合:-)然后,您可以考虑将以下简单方法添加到DisplayEvent
(或创建某种类型的助手班):
public static DisplayEvent combine(DisplayEvent evt1, DisplayEvent evt2)
{
if (evt1.getActivityTimestamp() == null)
evt1.setActivityTimestamp(evt2.getActivityTimestamp());
//TODO: transfer all names from evt2 to evt 1
// check if timestamps match, optimize, etc
return evt1;
}
public static DisplayEvent fromEvent(Event evt)
{
DisplayEvent dispEvt = new DisplayEvent();
//todo copy the necessary stuff to dispEvt
return dispEvt;
}
然后lambda可能看起来像这样:
Collection<DisplayEvent> displayEvents =
events.stream().collect(Collectors.groupingBy(
ev -> ev.activityTimestampProperty(),
Collectors.reducing(
new DisplayEvent(),
DisplayEvent::fromEvent,
DisplayEvent::combine))).values();
免责声明:我不太喜欢这个:-)所以我个人坚持使用非DisplayEvent
解决方案。
答案 1 :(得分:0)
这是我的解决方案,但不完全是我希望的lambda表达式。
events
.stream()
.collect(Collectors.groupingBy(ev -> ev.activityTimestampProperty().get()))
.forEach((key,v) -> {
DisplayEvent de = new DisplayEvent();
de.activityTimestamp.set(key);
for (Event event : v) {
de.userName.set(event.getUserName());
de.eventDescriptions.add(event.getEventDescription());
de.eventNames.add(event.geEventName());
}
displayActivities.add(dha);
});