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 项目


原始标题:Shuffle a List in Kotlin