分组加倍以映射以创建直方图

时间:2018-08-09 18:17:39

标签: java grouping histogram

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

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

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

2 个答案:

答案 0 :(得分:0)

只需将double的第一个参数中的int向下舍入到groupingBy。您的问题首先说明样本List包含Double,但是您的代码段表明它实际上是List<WindData>。是哪一个?

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

进行此操作。

答案 1 :(得分:0)

这是一个从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));

关于结果的注释:映射的键是间隔的下边界(00-111-2