【问题标题】:Grouping doubles to map to create histogram将双打分组以映射以创建直方图
【发布时间】:2018-08-09 18:17:39
【问题描述】:

假设我们有样本列表(Double 类型){1.5, 1.1, 2.2, 1.0, 2.2, 3.3}。如何实现将 In​​teger 作为键(组)并将出现次数作为该 Map 的值的 Map? 对于给定的示例 1 -> 3, 2 -> 2, 3 -> 1。我知道我可以使用 if/else if 或 case 逻辑来实现这一点,但在我的应用程序中它将是 30 个不同的组(代码中的 30 个 case 或 elseifs) . 应用程序正在根据从数据库(数百万个样本)中提取的给定风速创建风直方图。 我的做法:

Map<Double, Long> map = windData.stream()
.collect(Collectors.groupingBy(WindData::getSpeed, Collectors.counting()));

其中 windData 是保存风速的列表,而 getSpeed 是检索风速值。这种方法生成双打组,这意味着它只计算出现次数,我想得到 0-1、1-2、2-3、3-4 等组。

【问题讨论】:

    标签: java grouping histogram


    【解决方案1】:

    只需将double 向下舍入到groupingBy 的第一个参数中的int。您的问题首先说List of samples 包含Doubles,但您的代码 sn-p 表明它实际上是List&lt;WindData&gt;。是哪个?

    import static java.util.stream.Collectors.counting;
    import static java.util.stream.Collectors.groupingBy;
    ....
    
    List<Double> speeds = ...;
    Map<Integer, Long> histogram = speeds.stream()
                   .collect(groupingBy(Double::intValue, counting()));
    

    另外,除非您出于其他原因从数据库中提取此数据,否则请考虑使用 SQL group by 在数据库端执行此操作

    【讨论】:

    • WindData 是一个保存风数据的类。例如风速、测量风速的气象站名称等。在这种情况下,getSpeed 返回 Double。我的错,我应该提到这一点。
    • getSpeed的返回类型是什么?
    • 一个双精度值。
    • 那么你应该使用windspeed -&gt; windspeed.getSpeed().intValue()作为groupingBy的第一个参数
    • 当我尝试这个解决方案时,它会生成:Error:(33, 120) java: double cannot be dereferenced
    【解决方案2】:

    这是一个从double 值流中生成“直方图”数据的管道:

    HashMap<Double, Long> res = 
            DoubleStream.of(1.5, 1.1, 2.2, 1.0, 2.2, 3.3)
            .collect(HashMap<Double, Long>::new,
                     (map, dbl) -> map.merge(Math.floor(dbl), 1L, (k, v) -> k + v), 
                     (map1, map2) -> map1.putAll(map2));
    

    打印res 输出{2.0=2, 1.0=3, 3.0=1}

    要将其应用于您的对象流,我只需使用 mapToDouble 将其转换为双流:

    windData.stream().mapToDouble(WindData::getSpeed)
        .collect(HashMap<Double, Long>::new,
                     (map, dbl) -> map.merge(Math.floor(dbl), 1L, (k, v) -> k + v), 
                     (map1, map2) -> map1.putAll(map2));
    

    结果说明:map的key是区间的下边界(00-111-2

    【讨论】:

    • 不知道为什么,但对于我的示例,它生成的 Map 中只有两个值。键工作正常。
    • @Jabbasnik 我怀疑(k, v) -&gt; v + 1 应该是(k, v) -&gt; k + v。目前无法测试,但它似乎是我的代码中的一个错误,这解释了为什么它显示 2 作为键 1 的值,而它应该显示 3。
    • 此更改后,此解决方案与@Misha 解决方案一样有效。谢谢!
    猜你喜欢
    • 2016-04-29
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 2021-12-24
    • 2014-01-30
    相关资源
    最近更新 更多