Java 分组双重映射以创建直方图

Java 分组双重映射以创建直方图,java,grouping,histogram,Java,Grouping,Histogram,让我们假设,我们有样本列表(类型Double){1.5,1.1,2.2,1.0,2.2,3.3}。如何实现将整数作为键(组)并将出现次数作为该映射值的映射? 对于给定的示例1->3,2->2,3->1。我知道我可以通过if/else if或case逻辑实现这一点,但在我的应用程序中,它将是30个不同的组(代码中的30个case或elseif)。 应用程序正在根据从DB(数百万个样本)中提取的给定风速创建风直方图。 我的做法: Map<Double, Long> map = windD

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

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

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

只需将
double
四舍五入到
int
第一个参数中的
groupingBy
。首先,您的问题是样本的
列表
包含
s,但您的代码片段表明它实际上是一个
列表
。是哪一个

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()));
导入静态java.util.stream.Collectors.counting;
导入静态java.util.stream.Collectors.groupingBy;
....
列表速度=。。。;
地图直方图=速度。流()
.collect(分组方式(Double::intValue,counting());

在一个单独的注释中,除非您出于某种原因将此数据从数据库中取出,请考虑在数据库侧使用SQL <代码>组按 < /P> > P>这是一条从“代码>双值>流中生成“直方图”数据的管道:

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

注意结果:地图的关键点是区间的下边界(
0
0-1
1
1-2

WindData是保存风数据的类。例如风速、测量风速的气象站名称等。在本例中,getSpeed返回Double。我的缺点是我应该提到这一点。
getSpeed
的返回类型是什么?一个双精度值。然后你应该使用
windspeed->windspeed.getSpeed().intValue()
作为
groupingBy
的第一个参数,当我尝试这个解决方案时,它会生成:Error:(33120)java:Double不能被取消引用不确定为什么,但对于我的示例,它生成的映射中只有两个值。钥匙工作正常。@Jabbasnik我怀疑
(k,v)->v+1
应该是
(k,v)->k+v
。目前无法测试,但这似乎是我代码中的一个错误,这解释了为什么它显示2作为键1的值,而它应该显示3。在进行此更改后,此解决方案与@Misha解决方案一样有效。非常感谢。
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));