1. 概述

Kotlin 的标准库功能非常丰富。虽然底层基于 Java 标准库,但它扩展了大量便捷的函数式 API,这些在 Java 中往往需要手动实现。

其中一类在日常开发中极为实用的功能是集合的聚合操作(aggregation operations)。这类函数能将一个集合“归约”为单个值,典型的如 sum()average() 等。

本文重点介绍 Kotlin 中用于数值集合求和的 sum() 函数,它是处理数字列表时最常用的工具之一。

2. sum() 聚合函数详解

Kotlin 标准库中提供了多个重载版本的 sum() 函数:

✅ 针对每种基本数值类型的 Iterable<T> 扩展函数
✅ 针对每种基本数值类型的数组(Array)扩展函数

Int 类型为例,其核心实现如下:

public fun Iterable<Int>.sum(): Int {
    var sum: Int = 0
    for (element in this) {
        sum += element
    }
    return sum
}

✅ 基本行为特点

  • 空集合返回 0:无需额外判空处理,避免 NPE 风险
assert(listOf<Int>().sum() == 0) // true
  • 正常求和示例
listOf(
    16, 96, 100, 15, 30,
    70, 11, 31, 52, 70,
    42, 50, 56, 93, 57
).sum()
  .also { assertEquals(789, it) }

⚠️ 注意事项与潜在“踩坑”点

❌ 不做 null 检查,但前提是类型安全

由于 Iterable<Int> 是非空类型(primitive int),所以调用 sum() 时不会出现 null 导致的异常。但如果使用的是 List<Int?>,则必须先过滤或转换:

listOf<Int?>(1, 2, null, 4)
    .filterNotNull()
    .sum() // 正确做法

否则会抛出 NullPointerException —— 这是很多初学者容易忽略的点。

⚠️ 无溢出检查(No Overflow Protection)

sum() 不会检测整型溢出,也不会抛出异常。这意味着当总和超过 Int.MAX_VALUE 时会发生静默溢出:

listOf(Int.MAX_VALUE - 2, 1, 2, 4)
  .sum()
  .also { assert(-2147483644 == it) } // true,结果已溢出

📌 建议实践: 当预估总和可能接近 Int.MAX_VALUE 时,应提前转换为更大范围的类型:

// 方案一:转为 Long 避免溢出
list.map { it.toLong() }.sum()

// 方案二:使用 Double(接受精度损失)
list.sumOf { it.toDouble() }

或者通过估算判断是否需要升级类型:

if (list.average() * list.size > Int.MAX_VALUE) {
    // 使用 Long 或 Double 处理
}

💡 大数据量下的并行优化(适用于极端场景)

对于超大规模数据集(例如百万级以上元素),可考虑分片并行求和提升性能:

val executor = Executors.newFixedThreadPool(4)

val result = listOf(16, 96, 100, 15, 30, 70, 11, 31, 52, 70, 42, 50, 56, 93, 57)
    .asSequence()
    .chunked(5) // chunkSize 应根据 CPU 核心数和数据规模动态调整
    .map { executor.submit(Callable { it.sum() }) }
    .map { it.get() } // 获取每个线程的结果
    .sum()           // 最终合并

assertEquals(789, result)

⚠️ 但需注意:现代 CPU 的算术运算极快,sum() 属于 CPU 密集型任务,线程切换开销可能抵消并行收益。除非数据量极大,否则不建议过早优化。

📌 替代方案:若已在协程环境中,也可使用 async/awaitAll 实现类似效果,但此处普通线程池更直接高效。

3. 总结

sum() 是 Kotlin 集合库中最常用且高效的聚合函数之一,支持所有基本数值类型(Int, Long, Double 等),其返回类型遵循以下规则:

元素类型 返回类型
Byte / Short / Int Int
Long Long
Float / Double 对应类型

最佳实践建议

  • ✅ 优先使用标准库函数,避免重复造轮子
  • ✅ 注意整型溢出风险,必要时升阶到 LongDouble
  • ✅ 空集合安全,无需额外防护
  • ✅ 对 Int? 等可空类型需先 filterNotNull()
  • ✅ 极端大数据量才考虑并行化,小数据集反而降低性能

所有示例代码均可在 GitHub 上获取:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-collections-3


原始标题:Sum All the Items in a List of Integers in Kotlin