1. 概述
在日常开发中,比较多个数值并找出最大值是一个非常常见的需求。
本文将探讨如何在 Kotlin 中找出三个数中的最大值,并进一步扩展到从任意 n 个数中找出最大值的通用解法。
我们会从手写算法开始,逐步过渡到使用标准库函数,帮助你理解背后的逻辑和性能差异,避免踩坑。
2. 问题引入
从三个或更多数字中找出最大值本身并不是一个复杂的问题。Kotlin 标准库已经提供了现成的便捷方法。
但我们先不急着用轮子,而是✅从零实现自己的解决方案,顺便熟悉一些 Kotlin 的优雅语法特性——这对刚接触 Kotlin 的开发者尤其有帮助。
本文以 Int
类型为例,但所有方案均可适配其他 Number
子类型(如 Long
、Double
等)。
接下来,直接上代码。
3. 手动实现解决方案
3.1 使用 if-else 表达式
最直观的思路是:逐个判断每个数是否大于等于另外两个数。若前两个都不是最大值,则第三个必然是答案。
val a = 42
val b = 100
val c = -42
val result = if (a >= b && a >= c) {
a
} else if (b >= a && b >= c) {
b
} else {
c
}
assertEquals(100, result)
⚠️ 注意:Kotlin 中的 if
是表达式(expression),可以返回值,因此可以直接赋值给变量。这是和 Java 的关键区别之一。
3.2 使用 when 表达式优化可读性
同样的逻辑,改用 when
表达式会让代码更清晰:
val (a, b, c) = listOf(42, 100, -42)
val result = when {
a >= b && a >= c -> a
b >= a && b >= c -> b
else -> c
}
assertEquals(100, result)
这里还用到了 Kotlin 的解构声明(destructuring declaration),一行代码初始化三个变量,简洁又高效。
时间复杂度分析 ❌
该算法最坏情况下需要进行 4 次比较(每数两次)。推广到 n 个数时,若采用类似两两对比的方式,比较次数可达 (n-1)²,时间复杂度为 O(n²) —— 显然不适合大规模数据。
3.3 优化算法:链式比较 ✅
更好的思路是:先比较前两个数得出较大者,再与第三个数比较。只需 2 次比较即可得出结果。
推广到 n 个数时,只需遍历一次,时间复杂度为 **O(n)**。
实现如下:
val (a, b, c) = listOf(42, 100, -42)
val maxOfAB = if (a >= b) a else b
val result = if (c >= maxOfAB) c else maxOfAB
assertEquals(100, result)
这个模式简单高效,适合手动实现且易于理解。
4. 使用 math.max() 方法
Kotlin 提供了 kotlin.math.max(a, b)
函数,用于返回两个数中的较大值。
我们可以嵌套调用两次,轻松解决三数取最大:
val (a, b, c) = listOf(42, 100, -42)
val result = max(max(a, b), c)
assertEquals(100, result)
✅ 优点:代码极简,语义清晰
⚠️ 缺点:无法直接处理空值或集合;对于更多数字需多次嵌套,不够灵活
📌 提示:
max()
来自kotlin.math
包,需确保导入正确包路径
5. 处理 n 个数的情况
实际开发中,我们面对的往往是集合形式的数据(如 List<Int>
)。幸运的是,Kotlin 集合 API 提供了原生支持。
5.1 使用 max()
直接调用 max()
即可获取集合中的最大值:
val nNumbers = listOf(42, 100, -42, 20, 43, -2, 103, 420)
val result = nNumbers.max()
assertEquals(420, result)
❌ 踩坑警告:如果列表为空,max()
会抛出 NoSuchElementException
!
assertThrows<NoSuchElementException> { emptyList<Int>().max() }
这在生产环境中极易引发运行时异常,务必小心。
5.2 推荐方案:使用 maxOrNull()
为了安全起见,当集合可能为空时,应使用 maxOrNull()
:
val possibleMax = emptyList<Int>().maxOrNull()
assertNull(possibleMax)
✅ 返回 Int?
类型,空集合返回 null
,避免崩溃,更适合业务逻辑处理。
方法 | 是否允许空集合 | 返回类型 | 建议场景 |
---|---|---|---|
max() |
❌ 抛异常 | Int |
确保非空时使用 |
maxOrNull() |
✅ 返回 null | Int? |
通用推荐,更安全 |
6. 总结
本文我们实现了两种找最大值的手动算法:
- 基于多重条件判断(O(n²))
- 链式比较法(O(n)),更高效
随后介绍了 Kotlin 标准库中的实用方法:
kotlin.math.max(a, b)
:适用于固定两个数的比较Collection.max()
与maxOrNull()
:处理集合数据的首选,后者更安全
📌 最佳实践建议:
- 小范围比较可用
max(max(a,b), c)
- 集合操作优先使用
maxOrNull()
防止 NPE - 理解底层逻辑才能写出健壮代码,别盲目依赖 API
完整示例代码已托管至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/kotlin-math