1. 简介

在 Kotlin 中,Set 是一种不允许重复元素的集合类型。在实际开发中,我们经常会遇到需要对一个 Set 进行“复制”或“克隆”的场景——比如要在副本上做修改,但又不能影响原始数据。

本文将介绍几种在 Kotlin 中安全克隆 Set 的方法,并结合 JUnit 单元测试代码进行演示,帮助你在项目中避免踩坑。

✅ 目标:创建一个与原 Set 元素相同但独立的新对象
❌ 错误做法:直接赋值(如 val cloned = originalSet),这只会复制引用,不是深拷贝

2. 使用 toSet() 方法

最简单、最常用的方式就是调用 toSet() 扩展函数。它会返回一个包含原集合所有元素的新 Set 实例

@Test
fun `Clone set using toSet`() {
    val originalSet = setOf("apple", "banana", "cherry")

    val clonedSet = originalSet.toSet()

    assertEquals(originalSet, clonedSet)       // 内容相等 ✅
    assertNotSame(originalSet, clonedSet)     // 不是同一个对象 ✅
}

⚠️ 注意:即使原 Set 是可变的(MutableSet),调用 toSet() 后返回的是不可变 Set。如果你后续需要修改副本,请使用下面的方法。

这个方法适用于大多数只读场景,简洁明了,推荐优先使用。

3. 使用 toMutableSet() 创建可变副本

当你需要对克隆后的 Set 进行增删操作时,就应该使用 toMutableSet()。它返回的是一个 MutableSet 类型的副本。

@Test
fun `Clone set using toMutableSet`() {
    val originalSet = setOf("apple", "banana", "cherry")
    val clonedSet = originalSet.toMutableSet()

    assertEquals(originalSet, clonedSet)
    assertNotSame(originalSet, clonedSet)

    assertInstanceOf(MutableSet::class.java, clonedSet)
}

✅ 优势:

  • 返回的是可变集合,支持 addremove 等操作
  • 类型明确,IDE 能正确推导

📌 小贴士:如果你是从 DAO 或 Service 层获取了一个不可变 Set,但在业务逻辑中需要临时修改,toMutableSet() 是最安全的选择。

4. 使用 Set 构造函数手动创建

你也可以通过具体实现类的构造函数来克隆 Set,例如使用 HashSet 构造器传入原始集合。

@Test
fun `Clone set using constructor`() {
    val originalSet = setOf("apple", "banana", "cherry")

    val clonedSet = HashSet(originalSet)

    assertEquals(originalSet, clonedSet)
    assertNotSame(originalSet, clonedSet)
}

这种方式的好处是你可以指定底层实现类型:

  • HashSet:基于哈希表,无序
  • LinkedHashSet:保持插入顺序
  • TreeSet:自动排序(要求元素可比较)

🌰 示例:如果你想保留插入顺序并可变,可以这样写:

val clonedSet = LinkedHashSet(originalSet)

⚠️ 注意:这种方式虽然灵活,但会引入具体实现类的依赖,降低抽象性。除非有特殊需求(如性能优化、排序等),否则建议优先使用标准库函数(如 toSet())。

5. 总结

方法 是否可变 是否推荐 适用场景
toSet() ❌ 不可变 ✅ 强烈推荐 通用只读副本
toMutableSet() ✅ 可变 ✅ 推荐 需要修改副本内容
构造函数(如 HashSet(set) 取决于实现 ⚠️ 按需使用 特定实现需求(如排序、顺序)

在日常开发中,**优先使用 toSet()toMutableSet()**,它们语义清晰、代码简洁,且由标准库保证行为一致性。

所有示例代码均已上传至 GitHub:https://github.com/baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-collections-set


原始标题:Clone a Set in Kotlin