假设我们有样本列表(类型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等组。
答案 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));
关于结果的注释:映射的键是间隔的下边界(0
是0-1
,1
是1-2
)