【问题标题】:How to Group Objects in a List into other Lists by Attribute using streams & Java 8?如何使用流和 Java 8 按属性将列表中的对象分组到其他列表中?
【发布时间】:2015-05-23 17:44:48
【问题描述】:

我想将包含 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 及其功能的使用越来越多,我们可以找到解决此类问题的解决方案。

问候, 克拉斯 M.

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

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

注意:列表必须在之后进行排序。

【问题讨论】:

    标签: list lambda java-8 java-stream


    【解决方案1】:

    这完全没问题:

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

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

    【讨论】:

      【解决方案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&lt;Integer, List&lt;Tick&gt;&gt;,其中的键是从baseTime 开始的五分钟存储桶的索引,以及该存储桶中的刻度列表。如果您只想要一个直方图,请使用下游收集器:

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

      【讨论】:

      • @HarshPoddar 由你决定。我试图说明如何分解问题,因为这似乎是 OP 遇到问题的地方。
      • 感谢您的回答!
      猜你喜欢
      • 1970-01-01
      • 2020-05-20
      • 2016-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多