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

时间:2015-05-23 17:44:48

标签: list lambda java-8 java-stream

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

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

(你可以在这里找到主题:How to group elements of a List by elements of another in Java 8

我想到了类似的东西:

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

这当然是最好的工作。

我希望,Java 8&amp;它的功能越来越多,我们可以为这样的问题找到一个suting解决方案。

此致 Claas M。

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

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

注意:之后必须对List进行排序。

2 个答案:

答案 0 :(得分:4)

这完全没问题:

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

此方法将为您提供一个地图,您可以在该地图上调用.values()以获取列表列表。第一个元素将包含obj.getTime()从0到intervalLength的元素,只要有这样的元素。第二个将包含intervalLength到intervalLength * 2,依此类推

答案 1 :(得分:4)

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

// 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());