在这里插入图片描述

本文是 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.* 依赖,真正做到"算法层与平台解耦"。

二、适配总思路:三层架构(纯语义复刻)

  1. 语义层(零 @kit.*):PersistentList 用 cons 链表(head + tail 指向上一个节点)承载,实现 O(1) add 与不可变性。
  2. 引擎层(零平台桥接):OhosImmutableEngine 不桥任何系统 API,而是承接 sharesBacking(结构共享检测)与 contentEquals(内容相等)两个验证工具——因为该库本就是纯算法,无需平台桥。
  3. 验收页: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 真实生效。下面三张截图分别是不可变性验证、结构共享检测与持久化映射的运行结果,可对照上文逐条核对。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

六、踩坑小结

  1. 泛型在 ArkTS 严格模式支持良好:PersistentList<T> / PersistentMap<K,V> 直接声明即可,无需特殊注解。
  2. 不可变字段用 readonly:配合显式构造赋值,既表达语义又满足严格模式。
  3. JSON.stringify 不能直接序列化类实例:验收页用 toArray() 转成原生数组后再 JSON.stringify,避免输出 {}。
  4. 纯算法库无需引擎层桥接:该库本身零平台依赖,引擎层只做验证工具,反而更清晰地体现了"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

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐