Kotlin Multiplatform for OpenHarmony 实战:kotlinx-collections-immutable 持久化集合适配

本文是 KMP 三方库鸿蒙化适配,聚焦 kotlinx-collections-immutable(Kotlin 官方持久化集合)的 OpenHarmony 适配。我们只讲本仓库真实落地的代码,不做系列横向对比。全文约 5 分钟可读完,适合正在做 KMP 库鸿蒙化、或想了解 ArkTS 如何承载纯算法语义的读者。
目录
一、为什么选它
kotlinx-collections-immutable 提供「持久化集合」:PersistentList / PersistentMap / PersistentSet。它的核心卖点不是"不可变"本身(Kotlin 的 List 本来就只读),而是结构共享——任何修改都返回一个新集合,原集合保持不变,且新旧集合共享底层节点,因此 add 是 O(1) 而非 O(n) 复制。这在需要频繁"快照"状态、又不想承担拷贝开销的场景(如撤销栈、状态管理、函数式数据流)里尤其有价值。
到了 OpenHarmony,这套数据结构没有任何平台特定依赖(不碰网络、不碰存储、不碰 UI),纯算法即可复刻。我们用 ArkTS 泛型 + 只读字段完整还原其语义,并真实演示"旧列表在 add 后不变"与"结构共享",证明 Kotlin 的持久化集合在鸿蒙同样成立。整个适配过程不引入任何 @kit.* 依赖,真正做到"算法层与平台解耦"。
二、适配总思路:三层架构(纯语义复刻)
- 语义层(零
@kit.*):PersistentList用 cons 链表(head + tail 指向上一个节点)承载,实现 O(1)add与不可变性。 - 引擎层(零平台桥接):
OhosImmutableEngine不桥任何系统 API,而是承接sharesBacking(结构共享检测)与contentEquals(内容相等)两个验证工具——因为该库本就是纯算法,无需平台桥。 - 验收页:
ImmutableCollectionsDemo在真机/模拟器上演示不可变性 + 结构共享 + 持久化映射。
三、语义层:cons 链表实现持久化列表
ImmutableCollections.ets 只承载数据与算法,零平台依赖(注意 ArkTS 严格模式禁止构造参数属性,字段显式赋值):
export class PersistentListNode<T> {
readonly head: T;
readonly tail: PersistentListNode<T> | null;
constructor(head: T, tail: PersistentListNode<T> | null) {
this.head = head;
this.tail = tail;
}
}
export class PersistentList<T> {
add(element: T): PersistentList<T> {
// 新节点 tail 指向旧根 ⇒ O(1),且新列表与旧列表共享全部历史节点
const newRoot = new PersistentListNode<T>(element, this.root);
return new PersistentList<T>(newRoot, this.count + 1);
}
}
要点:
- O(1) 添加:
add只 new 一个头节点,旧列表的整条尾巴被直接复用,无需复制。 - 不可变性:
add永不修改this.root,原列表引用与内容都不变;这与ArrayList.add原地改写的语义根本不同。 get(index):沿tail走count-1-index步,顺序与用户预期一致(索引 0 是第一个加入的元素)。
PersistentMap 则用 K/V 双数组承载,put 返回新映射、原映射不变——同样的不可变性契约。
四、引擎层:结构共享是灵魂
OhosImmutableEngine.ets 提供 sharesBacking:
sharesBacking<T>(a: PersistentList<T>, b: PersistentList<T>): boolean {
const rootB = b.rootNode();
if (rootB === null) return false;
// b 的根节点 tail 指向 a 的根节点 ⇒ 物理共享底层节点
return rootB.tail === a.rootNode();
}
若 b = a.add(x),b 的根节点就是为 x 新建的节点,它的 tail 正是 a 的根节点——所以 sharesBacking(a, b) 为 true,这是"结构共享"在物理层面的直接证据,也是持久化集合比"每次复制数组"高效的根本原因。换句话说,add 一次只新增一个节点,其余节点全部复用,时间复杂度 O(1)、空间开销 O(1)。
五、验收页:真机上验证
开发界面如下:

ImmutableCollectionsDemo.ets 三个按钮:
- 不可变性验证:
l1=[1,2,3],l2=l1.add(4)后 l1 仍[1,2,3],l2 为[1,2,3,4],证明原列表未被改写。 - 结构共享检测:
sharesBacking(l1, l2)返回true,证明 l2 复用 l1 的底层节点(O(1) 零拷贝)。 - 持久化映射:
m1={a:1},m2=m1.put('b',2)后 m1 仍{a:1},m2 为{a:1,b:2}。
结果区会显示三段正确输出,证明持久化集合 API 真实生效。下面三张截图分别是不可变性验证、结构共享检测与持久化映射的运行结果,可对照上文逐条核对。



六、踩坑小结
- 泛型在 ArkTS 严格模式支持良好:
PersistentList<T>/PersistentMap<K,V>直接声明即可,无需特殊注解。 - 不可变字段用
readonly:配合显式构造赋值,既表达语义又满足严格模式。 JSON.stringify不能直接序列化类实例:验收页用toArray()转成原生数组后再JSON.stringify,避免输出{}。- 纯算法库无需引擎层桥接:该库本身零平台依赖,引擎层只做验证工具,反而更清晰地体现了"Kotlin 算法在鸿蒙无缝复刻"。
本文记录 kotlinx-collections-immutable(Kotlin 官方持久化集合)在 OpenHarmony 上的真实适配过程。核心思路是「纯语义复刻」——该库零平台依赖,我们用 ArkTS 泛型 + 只读字段完整还原其语义,通过 cons 链表实现 O(1) add 与不可变性,用 sharesBacking 在物理层面验证结构共享,并在真机/模拟器上演示不可变性、结构共享与持久化映射三大特性。全文按「为什么选它 → 三层架构 → 语义层 → 引擎层 → 验收页 → 踩坑小结」展开,附完整可运行代码。
社区引导
欢迎加入 KMP&CMP 鸿蒙社区:https://atomgit.com/CPF-KMP-CMP
本适配全部源码已开源在 AtomGit:https://atomgit.com/wdracky/kmp-ohos-adapters/tree/main/kotlinx-collections-immutable
如果你在适配过程中用到了 AI 辅助工具,推荐码道(AtomCode)专属通道
https://developer.huaweicloud.com/codeartsco.html?source=dmzntgwatomgit1&sourcead=dmzntgwatomgiths
更多推荐



所有评论(0)