如何用Kotlin的groupingBy与aggregate实现按Key统计求和?
用Kotlin的groupingBy和aggregate实现按Key求和
嘿,你已经搞定了30GB大CSV文件的流式读取与转换,这一步做得相当漂亮!接下来用groupingBy和aggregate实现按Key统计求和,刚好能适配你这种大文件流式处理的场景,不会把全部数据加载到内存里,完美契合需求。
核心实现代码
基于你已有的Sequence,直接链式调用分组和聚合操作即可:
// 你已经实现的Sequence生成逻辑 val dataSequence = File("data").walk() .filter { it.isFile } .flatMap { file -> println(file.toString()) file.inputStream().bufferedReader().lineSequence() } .map { line -> val (key, stuff, matchCount) = line.split(",") Triple(key, stuff, matchCount.toInt()) } // 按Key求和的核心逻辑 val sumByKey: Map<String, Int> = dataSequence .groupingBy { it.first } // 以Triple中的key作为分组依据 .aggregate { _, accumulator: Int?, element, isFirst -> // 组内第一个元素:直接取它的matchCount作为累加初始值 if (isFirst) { element.third } else { // 后续元素:将当前累加值与新元素的matchCount相加 accumulator!! + element.third } }
代码细节拆解
groupingBy { it.first }:
这个方法会创建一个流式的Grouping对象,指定用Triple的第一个元素(也就是你的key)作为分组标识。所有相同key的元素会被归到同一组,而且整个过程是流式处理的,不会一次性加载所有数据到内存,非常适合你的大文件场景。aggregate自定义聚合:
这是实现自定义求和逻辑的核心,lambda参数的含义:_:当前组的key值,这里我们用不到,所以用下划线忽略accumulator:保存当前组的累加结果,初始状态为nullelement:当前遍历到的组内元素(就是你生成的Triple<String, String, Int>对象)isFirst:布尔值,标记当前元素是否是组内第一个被处理的元素- 逻辑上,第一个元素直接用它的
matchCount作为累加起点,后续每个元素都把当前累加值和新元素的matchCount相加,最终得到每个key的总计数。
额外小补充
如果之后你需要更复杂的聚合逻辑(比如同时统计求和、计数、最大值),aggregate也能轻松扩展,这也是它比简化版求和方法更灵活的地方。
内容的提问来源于stack exchange,提问作者Benjamin H
相关产品推荐
相关产品推荐

