资讯动态

仓颉标准库 ArrayList 的 get/set 访问详解:下标修改、Option 取值与越界语义

发布时间:2026/10/15 16:26:20 来源:尧图企业网站定制
编程语言语言运行时标准库垃圾回收并发编程【免费下载链接】cangjie_runtime仓颉编程语言运行时与标准库。项目地址https://gitcode.com/Cangjie/cangjie_runtime点击查看免费下载本指南以仓颉编程语言标准库cangjie_runtime 仓库stdlib/libs/std/collection中的ArrayList为对象系统讲解其元素读取get方法与修改下标赋值两类操作包括下标运算符list[i]与list[i] value的用法、get方法返回OptionT的设计动机、getOrThrow的安全取值方式以及越界访问时两种 API 截然不同的行为差异。读完本文你将掌握在仓颉中使用ArrayList进行索引读写的最佳实践并能依据源码理解其底层实现与异常契约。一、示例文档速览一次完整的读写演示stdlib/doc/libs/std/collection/collection_package_samples/sample_arraylist_get_set.md给出了一个可直接运行的示例先创建一个包含 5 个元素的ArrayListInt64随后用下标修改两处元素再用get方法配合getOrThrow读取指定索引的元素。完整代码与输出如下import std.collection.* main() { var list ArrayListInt64([10, 20, 30, 40, 50]) println(初始列表: ${list}) // 使用下标修改元素值 list[1] 25 println(修改索引1为25后: ${list}) list[3] 45 println(修改索引3为45后: ${list}) // 使用get方法获取元素 var value0 list.get(0) println(索引0的元素: ${value0.getOrThrow()}) var value2 list.get(2) println(索引2的元素: ${value2.getOrThrow()}) return 0 }运行结果初始列表: [10, 20, 30, 40, 50] 修改索引1为25后: [10, 25, 30, 40, 50] 修改索引3为45后: [10, 25, 30, 45, 50] 索引0的元素: 10 索引2的元素: 30该示例通过注释中的!-- verify --标记参与仓库的自动化校验读者可以在本地环境中直接复现验证。二、ArrayList 是什么可扩容数组实现在进入读写细节之前先明确ArrayList的定位。依据 array_list.cj 中的类定义ArrayListT是Collection接口的可扩容数组Resizable-array实现继承自ListT接口允许存放包括null在内的所有元素。从源码结构看其内部存储模型非常直白var myData: ArrayT真正的底层元素数组array_list.cjvar mySize: Int64当前逻辑元素个数array_list.cjvar myVersion: Int64版本号用于迭代器检测并发修改array_list.cjDEFAULT_CAPACITY 16默认初始容量array_list.cjcapacity属性直接返回底层数组长度myData.sizearray_list.cj。当元素数量达到容量上限触发扩容时grow方法采用oldCapacity (oldCapacity 1)的策略即按 1.5 倍增长并把旧数据拷贝到新数组array_list.cj。这保证了get/set这类按索引访问的操作是 O(1) 常数时间与链式结构形成鲜明对比。三、两种读取 API 的对比get 方法与下标运算符3.1 get 方法返回 Option 越界不抛异常get是ReadOnlyListT接口声明的成员list_interface.cj在ArrayList中的实现为array_list.cjpublic func get(index: Int64): ?T { if (index mySize || index 0) { return OptionT.None } return myData.get(index) }其关键设计是索引越界时不抛异常而是返回OptionT.None只有索引合法时才真正访问底层数组返回类型是?T即OptionT调用方必须显式处理“值可能不存在”的情况。因此示例中的list.get(0).getOrThrow()语义是先取索引 0 的OptionInt64再通过getOrThrow解包出实际值10。3.2 下标运算符 []直接返回 T越界抛异常与get不同下标读取运算符[]采用快速失败语义array_list.cjpublic operator func [](index: Int64): T { checkRange(index) return this.myData[index] }checkRange会检查索引合法性array_list.cjprivate func checkRange(index: Int64): Unit { if (index mySize || index 0) { throw IndexOutOfBoundsException(Invalid index ${index}: size is ${mySize}.) } }即当下标小于 0 或大于等于size时直接抛出IndexOutOfBoundsException。这种“越界即异常”的语义便于尽早暴露程序缺陷适合在索引必然合法的场景使用。3.3 选择建议场景推荐 API越界行为返回值索引必然合法、希望快速暴露错误list[i]抛IndexOutOfBoundsExceptionT直接可用索引可能越界、需要安全判空list.get(i)返回None不抛异常?TOptionT对Option结果直接解包list.get(i).getOrThrow()越界时抛NoneValueExceptionT示例文档选用的getgetOrThrow组合正是“安全取值 显式解包”的典型写法。四、getOrThrow 解包Option 的取值契约get返回的OptionT定义于 option.cj是一个枚举类型public enum OptionT { Some(T) | None }getOrThrow提供了两种重载无参版本option.cj当值为Some(v)时返回v为None时抛出NoneValueException带参版本option.cj允许调用方自定义异常工厂None时抛出exception()产生的异常适合转换为业务自定义错误。此外Option还提供了getOrDefault、isNone、isSome、map等方法option.cj可以组合出更优雅的空值处理链。需要强调的是get本身不会抛IndexOutOfBoundsException而getOrThrow解包None时抛出的是NoneValueException——二者异常类型不同这是示例代码背后容易被忽略的语义细节。五、下标修改元素set 运算符的实现示例中list[1] 25的赋值操作由ListT接口声明的下标赋值运算符支持list_interface.cjArrayList中的实现为array_list.cjpublic operator func [](index: Int64, value!: T): Unit { if (index mySize || index 0) { throw IndexOutOfBoundsException(Invalid index ${index}: expected 0 to ${mySize}.) } unsafe { myData.setUnchecked(index, value) } }实现要点越界检查与下标读取一致越界抛IndexOutOfBoundsException错误信息会给出期望的合法区间0 to ${mySize}底层写入检查通过后使用unsafe块的setUnchecked直接写入底层数组——由于越界已被拦截可省去重复的边界检查以提升性能原地修改set操作不会改变列表大小只能修改已存在索引上的值新增元素应使用add系列方法。值得注意赋值运算符实现没有递增myVersion。这意味着迭代过程中用下标修改已存在元素不会触发ConcurrentModificationException而add/remove等改变结构的方法会通过myVersion使迭代器失效参见 array_list.cj 中add的实现及 array_list.cj 中迭代器对版本号的校验。六、相关扩展范围切片与更多索引能力ArrayList的索引访问能力不止单元素读写还包括范围切片list[range]重载返回一个新的ArrayListTarray_list.cj内部调用slice(range)array_list.cj。slice要求range.step 1否则抛IllegalArgumentException范围起始大于结束时抛IndexOutOfBoundsExceptionarray_list.cj首尾元素快捷访问first与last属性分别返回get(0)与get(mySize - 1)类型为?Tarray_list.cj空列表时last返回None。这些能力与本文的get/set共同构成了ArrayList完整的按索引操作体系更多示例可参考同目录下的 sample_arraylist_add.md 与 sample_arraylist_remove_clear_slice.md。七、小结读取元素list.get(i)返回OptionT越界得None配合getOrThrow()解包None时抛NoneValueException下标读取list[i]越界直接抛IndexOutOfBoundsException适合索引必然合法的场景修改元素list[i] value原地写入底层数组越界抛异常不改变列表大小、不影响结构版本号底层保证ArrayList是 O(1) 随机访问的可扩容数组1.5 倍扩容策略由grow实现接口契约定义于ReadOnlyList/List。示例文档 sample_arraylist_get_set.md 与源码 array_list.cj 相互印证是理解仓颉标准库索引访问语义最直接的入口。赞分享编程语言语言运行时标准库垃圾回收并发编程【免费下载链接】cangjie_runtime仓颉编程语言运行时与标准库。项目地址https://gitcode.com/Cangjie/cangjie_runtime点击查看免费下载相关推荐仓颉编程语言 ArrayList 的 add 函数详解四种添加方式、索引定位与 Option 取值实战仓颉编程语言 ArrayList 的 add 函数详解四种添加方式、索引定位与 Option 取值实战 导读 本文围绕仓颉编程语言 std.collectio文档知识库教程OpenHarmony仓颉语言 std.collectionArrayList 的 get 与 set 函数使用详解仓颉语言 std.collectionArrayList 的 get 与 set 函数使用详解 本文以 sample_arraylist_get_set.md文档知识库教程OpenHarmony仓颉标准库 collection 并发修改异常 ConcurrentModificationException 完全指南仓颉标准库 collection 并发修改异常 ConcurrentModificationException 完全指南 导读 本文基于仓颉Cangjie标编程语言语言运行时标准库垃圾回收并发编程上一篇Pinpoint Elasticsearch 插件深度解析基于 RestHighLevelClient 的搜索与写入全链路 APM 监控下一篇kspack-rust性能优化指南7个技巧让你的数据编码速度翻倍创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑