如何使用流 & Java 8 按属性将列表中的对象分组到其他列表中?

How to Group Objects in a List into other Lists by Attribute using streams & Java 8?

我想将包含 time 属性的对象列表分组为 5 分钟间隔,最好使用流和收集器。

我在 Whosebug 上找到的唯一可能的解决方案是计算我需要多少间隔(子列表),将每个对象添加到这些列表中的每一个并过滤掉不适合相应时间范围的对象,这不是一个很好的解决方案。

(您可以在这里找到主题:

我想到了类似的东西:

List<MyObject> list = new ArrayList<MyObject>();
.......
List<List<MyObject>> grouped = list.stream().collect(Collectors.groupingBy(obj -> obj.getTime() / intervalLength));

这当然行得通。

希望随着Java8及其功能的使用越来越多,我们可以找到解决此类问题的方法。

此致, 克拉斯 M.

编辑: 最后,我使用了@Harsh Poddar 的解决方案,并使用

将地图转换为列表列表
for(Map.Entry<Integer, List<MyObject>> entry:map.entrySet())
  list.add(entry.getValue());

注意:List 之后需要进行排序。

这完全没问题:

Map<Long,<List<MyObject>> grouped = ticks.stream().collect(Collectors.groupingBy(obj -> obj.getTime() / intervalLength));

此方法将为您提供一张地图,然后您可以在该地图上调用 .values() 以获取列表列表。第一个元素将包含 obj.getTime() 从 0 到 intervalLength 的元素,前提是存在这样的元素。第二个将包含从 intervalLength 到 intervalLength*2 等等

使用函数将时间映射到存储桶:

// assume time is in seconds
int bucketNumber(int baseTime, int thisTime) {
    return (thisTime - baseTime) / 300;
}

然后按桶号收集:

ticks.stream().collect(groupingBy(e -> bucketNumber(baseTime, e.getTime()));

现在您有一个 Map<Integer, List<Tick>>,其中键是从 baseTime 开始的五分钟时段的索引,以及该时段中的滴答列表。如果您只想要直方图,请使用下游收集器:

ticks.stream().collect(groupingBy(e -> bucketNumber(baseTime, e.getTime()), 
                                  counting());