ArkTS中 LinkedList与ArrayList的对比

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

开发中,LinkedList和ArrayList是两种最常用的线性表实现,它们在内部结构、性能特性和适用场景上有显著差异:

一、底层实现差异

特性LinkedListArrayList
数据结构双向链表动态数组
内存分配非连续内存(节点分散存储)连续内存空间
节点结构包含前驱/后继指针和数据域仅存储数据
扩容机制无扩容概念(按需创建节点)容量不足时1.5倍扩容

二、操作性能对比

1. 访问操作

// ArrayList访问示例(O(1))
const arrList = new ArrayList<number>([1, 2, 3]);
arrList.get(1);  // 直接通过索引访问

// LinkedList访问示例(O(n))
const linkedList = new LinkedList<number>();
linkedList.add(1);
linkedList.add(2);
linkedList.get(1);  // 需要从头遍历

性能关键

  • ArrayList通过数组索引直接访问,时间复杂度O(1)
  • LinkedList需要遍历节点,平均时间复杂度O(n)

2. 插入/删除操作

// ArrayList中间插入(O(n))
arrList.addByIndex(1, 5);  // 需要移动后续元素

// LinkedList中间插入(O(1)已知节点位置)
linkedList.insert(1, 5);  // 仅修改指针

性能关键

  • 头部操作:LinkedList O(1),ArrayList O(n)
  • 中间操作:LinkedList O(1)(已知位置)/O(n)(需查找),ArrayList O(n)
  • 尾部操作:ArrayList O(1)(摊销),LinkedList O(1)

三、内存特性对比

内存特性LinkedListArrayList
内存占用更高(每个节点含两个指针)更低(仅存储数据)
内存局部性差(节点分散)好(连续存储)
缓存命中率
GC压力更大(频繁创建/销毁节点)更小

四、功能接口差异

1. 独有方法

LinkedList特有

.addFirst(element: T): void      // 头部添加
.addLast(element: T): void       // 尾部添加
.removeFirst(): T                // 移除头部
.removeLast(): T                 // 移除尾部

ArrayList特有

.trimToCurrentLength(): void     // 缩容到当前尺寸
.increaseCapacityTo(newCapacity: number): void  // 手动扩容

2. 迭代器差异

// LinkedList迭代器更适合修改操作
const lit = linkedList[Symbol.iterator]();
while (lit.next().done) {
  lit.remove();  // 安全删除当前元素
}

// ArrayList迭代器更适合随机访问
const ait = arrList[Symbol.iterator]();
ait.next().value;  // 快速获取元素

五、典型应用场景

推荐使用LinkedList的场景

  1. 频繁在头/中部插入删除
   // 消息队列实现
   const messageQueue = new LinkedList<string>();
   function processMessages() {
     while (messageQueue.length > 0) {
       const msg = messageQueue.removeFirst();
       // 处理消息...
     }
   }

   2. 实现栈/双端队列

   // 使用LinkedList实现撤销栈
   const undoStack = new LinkedList<Command>();
   function executeCommand(cmd: Command) {
     undoStack.addFirst(cmd);
     // 执行命令...
   }

3. 不确定数据规模的场景

   // 动态增长的日志记录
   const logEntries = new LinkedList<LogEntry>();
   function addLogEntry(entry: LogEntry) {
     logEntries.addLast(entry);  // 无需考虑容量
   }

推荐使用ArrayList的场景

  1. 频繁随机访问
   // 图片缓存池
   const imageCache = new ArrayList<PixelMap>(100);
   function getImage(index: number): PixelMap {
     return imageCache.get(index);  // O(1)访问
   }

2. 需要内存紧凑的场景

   // 渲染顶点数据
   const vertices = new ArrayList<Point>(1000);
   function addVertex(point: Point) {
     vertices.add(point);  // 连续内存提高渲染效率
   }

七、建议

  1. 选择LinkedList当

    • 需要频繁在头部/中部插入删除
    • 数据规模变化大且不可预测
    • 需要实现队列/栈等数据结构
    • 不关心随机访问性能
  2. 选择ArrayList当

    • 需要频繁按索引访问元素
    • 数据量相对稳定或可预测
    • 追求内存使用效率
    • 需要进行数值计算
  3. 混合使用建议

   // 读多写少的场景:ArrayList为主
   const dataCache = new ArrayList<Data>();
   
   // 写操作专用缓冲区:LinkedList
   const writeBuffer = new LinkedList<Data>();
   
   function syncData() {
     // 批量转移数据
     dataCache.addAll(Array.from(writeBuffer));
     writeBuffer.clear();
   }
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值