1. 概述
我们在开发中经常会遇到需要将列表中的元素随机打乱顺序的场景。
在本教程中,我们将探讨在 Kotlin 中实现列表打乱的多种方法,并重点分析 shuffled()
、shuffled(Random)
和 shuffle()
等标准库函数的使用方式和行为差异。
2. 问题背景
打乱列表看似简单,但 Kotlin 中的 List
有只读和可变之分,而且不同打乱方法的行为会根据参数或列表类型而有所不同。如果对这些函数理解不到位,很容易踩坑。
✅ Kotlin 提供了以下几种打乱函数:
shuffled()
:适用于只读和可变列表,返回新打乱后的列表。shuffled(random: Random)
:使用指定的随机源打乱顺序。shuffle()
:仅适用于MutableList
,在原地修改列表。
因此,我们需要明确每种函数的适用场景和行为。
3. 打乱只读列表
我们先初始化一个只读列表:
val readOnlyList = ('A'..'Z').toList()
这个列表包含了从 A 到 Z 的 26 个大写字母,顺序是固定的。
3.1 使用 shuffled()
这是最简单的方式:
val result = readOnlyList.shuffled()
println(
"""
|Before Shuffling:
|$readOnlyList
|Shuffled result:
|$result""".trimMargin()
)
输出示例:
Before Shuffling:
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
Shuffled result:
[P, G, K, E, T, N, O, I, M, Q, C, B, U, F, A, V, Y, Z, J, H, W, S, X, D, R, L]
⚠️ 注意:shuffled()
基于 Random
实现,每次调用结果都不同。
3.2 使用 shuffled(random: Random)
如果我们希望每次打乱的结果可重复,可以传入一个指定的 Random
实例:
val myRandomSeed = 42
val shuffleResults = listOf(
readOnlyList.shuffled(Random(myRandomSeed)),
readOnlyList.shuffled(Random(myRandomSeed)),
readOnlyList.shuffled(Random(myRandomSeed)),
)
assertEquals(1, shuffleResults.distinct().size)
这样可以确保使用相同 seed 的 Random
实例生成相同的打乱结果。
4. 打乱可变列表
可变列表 (MutableList
) 同样支持 shuffled()
和 shuffled(random: Random)
,但还可以使用 shuffle()
在原地直接修改列表。
4.1 使用 shuffled()
示例
val result = mutableList.shuffled()
println(
"""
|Before Shuffling:
|$readOnlyList
|Shuffled result:
|$result""".trimMargin()
)
输出示例:
Before Shuffling:
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
Shuffled result:
[D, G, I, U, A, K, L, T, H, E, S, X, Q, W, Z, V, Y, J, F, C, B, N, M, P, R, O]
4.2 使用 shuffle()
原地打乱
mutableList.shuffle()
println(
"""The original list:
|$mutableList""".trimMargin()
)
输出示例:
The original list:
[R, X, W, Q, V, S, M, J, T, F, U, H, Y, E, B, L, O, I, A, K, C, G, N, Z, P, D]
✅ 优势:不创建新列表,节省内存开销。
⚠️ 注意:shuffle()
是就地操作,会修改原始列表。
4.3 使用自定义随机源
我们也可以传入一个 Random
实例进行控制:
val myRandom = Random(123)
mutableList.shuffle(myRandom)
这样可以确保多次运行结果一致,适合用于测试或重现性要求高的场景。
5. 总结
在 Kotlin 中,我们可以使用以下方式打乱列表:
方法 | 类型 | 是否修改原列表 | 是否可重复 |
---|---|---|---|
shuffled() |
只读 / 可变 | ❌ | ❌ |
shuffled(random: Random) |
只读 / 可变 | ❌ | ✅ |
shuffle() |
仅可变 | ✅ | ❌ |
shuffle(random: Random) |
仅可变 | ✅ | ✅ |
✅ 推荐用法:
- 如果需要保留原始列表不变 → 使用
shuffled()
或shuffled(random)
- 如果允许修改原列表且希望节省内存 → 使用
shuffle()
或shuffle(random)
如需查看完整示例代码,欢迎访问 GitHub 项目。