容器类,顾名思义就是存储的类,用于存储各种数据类型的元素,并具备一系列处理数据元素的方法。在 arkui 开发框架中,容器类采用了类似静态的语言来实现,并通过 napi 框架对外提供。通过对存储位置以及属性的限制,让每种类型的数据都能在完成自身功能的基础上剪除冗余分支,保证了数据的高效访问,提升了应用的性能。本期,我们将为大家介绍 arkui 开发框架中容器类的各种类型以及相关 api 的使用。
容器类api介绍
在 arkui 开发框架中,提供了线性和非线性两类容器类,共 14 种,每种容器都有自身的特性及使用场景。下面,我们将为大家一一道来。 1.1线性容器类
线性容器类底层主要通过数组实现,包括 arraylist、vector、list、linkedlist、deque、queue、stack 七种。线性容器类 api,充分考虑了数据访问的速度,实现了运行时(runtime)通过一条指令就可以完成增删改查等操作。
1.1.1 arraylist
arraylist 即动态数组,可用来构造全局的数组对象。arraylist 依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为 10,并支持动态扩容,每次扩容大小为原始容量的 1.5 倍。arraylist 进行增、删、改、查操作的相关 api 如下:
1.1.2 vector
vector 是指连续存储结构,可用来构造全局的数组对象。vector 依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为 10,并支持动态扩容,每次扩容大小为原始容量的2倍。
由于 vector 扩容速度高于 arraylist,所以适用于数据添加比较频繁的场景。vector 在支持操作符访问的基础上,还增加了 get/set 接口,提供更为完善的校验及容错机制,满足用户不同场景下的需求。vector 进行增、删、改、查操作的相关 api 如下:
1.1.3 list
list 可用来构造一个单向链表对象,即只能通过头结点开始访问到尾节点。list 依据泛型定义,在内存中的存储位置可以是不连续的。
可以通过 get/set 等接口对存储的元素进行修改,list 进行增、删、改、查操作的相关 api 如下:
1.1.4 linkedlist
linkedlist 可用来构造一个双向链表对象,可以在某一节点向前或者向后遍历 list。linkedlist 依据泛型定义,在内存中的存储位置可以是不连续的。
可以通过 get/set 等接口对存储的元素进行修改,linkedlist 进行增、删、改、查操作的相关 api 如下:
1.1.5 queue
queue 可用来构造队列对象,存储元素遵循先进先出的规则。queue 依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为 8,并支持动态扩容,每次扩容大小为原始容量的 2 倍。queue 底层采用循环队列实现,入队及出队操作效率都比较高。queue 进行增、删、改、查操作的相关 api 如下:
1.1.6 deque
deque 可用来构造双端队列对象,存储元素遵循先进先出的规则,双端队列可以分别从对头或者队尾进行访问。deque 依据泛型定义,要求存储位置是一片连续的内存空间,其初始容量大小为 8,并支持动态扩容,每次扩容大小为原始容量的 2 倍。deque 底层采用循环队列实现,入队及出队操作效率都比较高。deque 进行增、删、改、查操作的相关 api 如下:
1.1.7 stack
stack 可用来构造栈对象,存储元素遵循后进先出的规则。stack 依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为 8,并支持动态扩容,每次扩容大小为原始容量的 1.5 倍。stack 底层基于数组实现,入栈出栈均从数组的一端操作,stack 进行增、删、改、查操作的相关 api 如下:
1.2非线性容器类
非线性容器类底层通过 hash 或者红黑树实现,包括 hashmap、hashset、treemap、treeset、lightweightmap、lightweightset、plainarray 七种。非线性容器类中的 key 及 value 的类型均满足 ecma 标准。
1.2.1 hashmap
hashmap 可用来存储具有关联关系的 key-value 键值对集合,存储元素中 key 是唯一的,每个 key 会对应一个 value 值。hashmap 依据泛型定义,集合中通过 key 的 hash 值确定其存储位置,从而快速找到键值对。hashmap 的初始容量大小为 16,并支持动态扩容,每次扩容大小为原始容量的 2 倍。hashmap 底层基于 hashtable 实现,冲突策略采用链地址法。hashmap 进行增、删、改、查操作的相关 api 如下:
1.2.2 hashset
hashset 可用来存储一系列值的集合,存储元素中 value 是唯一的。依据泛型定义。集合中通过 value 的 hash 值确定其存储位置,从而快速找到该值。hashset 初始容量大小为 16,支持动态扩容,每次扩容大小为原始容量的 2 倍。value 的类型满足 ecma 标准中要求的类型。hashset 底层基于 hashtable 实现,冲突策略采用链地址法。hashset 进行增、删、改、查操作的相关 api 如下:
1.2.3 treemap
treemap 可用来存储具有关联关系的 key-value 键值对集合,存储元素中 key 是唯一的,每个 key 会对应一个 value 值。treemap 依据泛型定义,集合中的 key 值是有序的,treemap 的底层是一棵二叉树,可以通过树的二叉查找快速地找到键值对。key 的类型满足 ecma 标准中要求的类型。treemap 中的键值是有序存储的。treemap 底层基于红黑树实现,可以进行快速地插入和删除。treemap 进行增、删、改、查操作的相关 api 如下:
1.2.4 treeset
treeset 可用来存储一系列值的集合,存储元素中 value 是唯一的。treeset 依据泛型定义,集合中的 value 值是有序的,treeset 的底层是一棵二叉树,可以通过树的二叉查找快速地找到该 value 值,value 的类型满足 ecma 标准中要求的类型。treeset 中的值是有序存储的。treeset 底层基于红黑树实现,可以进行快速地插入和删除。treeset 进行增、删、改、查操作的相关 api 如下:
1.2.5 lightweightmap
ligthweightmap 可用来存储具有关联关系的 key-value 键值对集合,存储元素中 key 是唯一的,每个 key 会对应一个 value 值。ligthweightmap 依据泛型定义,采用更加轻量级的结构,集合中的 key 值的查找依赖于 hash 值以及二分查找算法,通过一个数组存储 hash 值,然后映射到其他数组中的 key 值以及 value 值,key 的类型满足 ecma 标准中要求的类型。
初始默认容量大小为 8,每次扩容大小为原始容量的 2 倍。ligthweightmap 底层标识唯一 key 通过 hash 实现,其冲突策略为线性探测法,查找策略基于二分查找法。ligthweightmap 进行增、删、改、查操作的相关 api 如下:
1.2.6 lightweightset
ligthweightset 可用来存储一系列值的集合,存储元素中 value 是唯一的。ligthweightset 依据泛型定义,采用更加轻量级的结构,初始默认容量大小为 8,每次扩容大小为原始容量的 2 倍。集合中的 value 值的查找依赖于 hash 以及二分查找算法,通过一个数组存储 hash 值,然后映射到其他数组中的 value 值,value 的类型满足 ecma 标准中要求的类型。
ligthweightset 底层标识唯一 value 基于 hash 实现,其冲突策略为线性探测法,查找策略基于二分查找法。ligthweightset 进行增、删、改、查操作的相关 api 如下:
1.2.7 plainarray
plainarray 可用来存储具有关联关系的键值对集合,存储元素中 key 是唯一的,并且对于 plainarray 来说,其 key 的类型为 number 类型。每个 key 会对应一个 value 值,类型依据泛型的定义,plainarray 采用更加轻量级的结构,集合中的 key 值的查找依赖于二分查找算法,然后映射到其他数组中的 value 值。
初始默认容量大小为 16,每次扩容大小为原始容量的 2 倍。plainarray 的查找策略基于二分查找法。plainarray 进行增、删、改、查操作的相关 api 如下:
容器类的实现
下面我们将以 arraylist 为例,为大家介绍,容器类的实现。包括容器类的初始化、容器类的接口调用、容器类对象模型的构建以及拦截器处理。
2.1 容器类初始化
在 arkui 开发框架中,通过 napi 的统一框架对外层提供容器类。下面,我们将以 arraylist 为例,介绍基于 napi 的容器类的加载。如下图所示,是容器类初始化流程,在 napi 加载的过程中,会通过 arkprivate.load 接口加载对应的容器类。arraylist 在引擎中会初始化 constructor 以及 prototype 并返回,最后应用侧可以获得该容器类并使用。
2.2 容器类接口调用
在 arkui 开发框架中,容器类 api 的调用流程如下,用户先通过 new arraylist 进入引擎得到对应的 arraylist 对象,然后可以通过 add 接口向对象中添加元素,元素最终会添加到一片和该 arraylist 绑定的内存空间。可以通过 [] 操作符进行元素获取,对于容器类而言,引擎会直接通过快速路径访问到元素存储位置,返回该值。
2.3 容器类对象模型
在 arkui 开发框架中,构造容器类对象模型的流程如下图所示,在运行时禁止再向对象上添加 properties 属性,arraylist 借用对象模型中的 elements 位置存储元素。
实现说明:通过 elements 存储数组元素,length 为数组中元素个数,数组 capatity 可以通过 elements 的长度获取。
扩容策略:arraylist –> 1.5 倍
初始分配容量:arraylist -> 10
(注:ts 中的实现,扩容策略及初始分配容量不感知)
2.4 拦截器处理
拦截器处理,是指通过禁止掉一些影响对象行为的操作,比如 delete、setprototype 等,在运行时(runtime)维护一个高效的容器类对象。以 arraylist 为例,arkcompiler 内部拦截的操作主要涉及 deleteproperty、defineproperty、getproperty、setprototype、getownpropertykeys、hasproperty 等操作限制数组的 holy 添加,以及更改属性的 attributes 等操作,保证了不需要做 jsarray 必须做的 holy 判断、writable 判断等操作。
容器类api的使用
通过上文的介绍,相信大家对容器类已经有了比较深刻的认识。那么,我们怎么使用容器类 api 呢?本文列举常用的典型容器的使用示例,包括导入模块、增加元素、访问元素及修改等操作:
// arraylistimport arraylist from '@ohos.util.arraylist' // 导入arraylist模块let arraylist = new arraylist();arraylist.add(a);arraylist.add(1); // 增加元素print(arraylist[0]); // 访问元素arraylist[0] = one; // 修改元素print(arraylist[0]);// vectorimport vector from '@ohos.util.vector' // 导入vector模块let vector = new vector();vector.add(a);let b = [1, 2, 3];vector.add(b);vector.add(false); // 增加元素print(vector[0]); // 访问元素print(vector.getfirstelement()); // 访问元素// dequeimport deque from '@ohos.util.deque' // 导入deque模块let deque = new deque;deque.insertfront(a);deque.insertfront(1); // 增加元素print(deque[0]); // 访问元素deque[0] = one; // 修改元素print(deque[0]);// stackimport stack from '@ohos.util.stack' // 导入stack模块 let stack = new stack();stack.push(a);stack.push(1); // 增加元素print(stack[0]); // 访问元素stack.pop(); // 弹出元素print(stack.length);// listimport list from '@ohos.util.list' // 导入list模块let list = new list;list.add(a);list.add(1);let b = [1, 2, 3];list.add(b); // 增加元素print(list[0]); // 访问元素print(list.get(0)); // 访问元素// hashmapimport hashmap from '@ohos.util.hashmap' // 导入hashmap模块let hashmap = new hashmap();hashmap.set(a, 123);hashmap.set(4, 123); // 增加元素print(hashmap.haskey(4)); // 判断是否含有某元素print(hashmap.get(a)); // 访问元素// treemapimport treemap from '@ohos.util.treemap' // 导入treemap模块let treemap = new treemap();treemap.set(a, 123);treemap.set(6, 356); // 增加元素print(treemap.get(a)); // 访问元素print(treemap.getfirstkey(a)); // 访问首元素print(treemap.getlastkey(a)); // 访问尾元素// lightweightmapimport lightweightmap from '@ohos.util.lightweightmap' // 导入lightweightmap模块let lightweightmap = new lightweightmap();lightweightmap.set(x, 123);lightweightmap.set(8, 356); // 增加元素print(lightweightmap.get(a)); // 访问元素print(lightweightmap.get(x)); // 访问元素print(lightweightmap.getindexofkey(8)); // 访问元素// plainarrayimport plainarray from '@ohos.util.plainarray' // 导入plainarray模块let plainarray = new plainarray();plainarray.add(1, sdd);plainarray.add(2, sff); // 增加元素print(plainarray.get(1)); // 访问元素print(plainarray.getkeyat(1)); // 访问元素
至此以上就是本期全部内容,期待广大开发者通过 arkui 开发框架的容器类开发出更多高性能的应用。
Valens联手英特尔代工服务,运用前沿工艺制造MIPI A-PHY芯片组
小米成为西班牙智能手机出货量第一
RTB2000数字示波器的特点特性及应用范围
阿里工业互联网平台“思考”:一场从0到1的蜕变
32国家投资641亿联合开发自己的超算和处理器,企图领先中美等
OpenHarmony 3.1 Beta版本关键特性解析——ArkUI开发框架容器类API的介绍与使用
比亚迪刀片电池技术工艺流程解析
华为老兵眼中的上海滩无线和芯片30年史
pcb走线为什么要45度?pcb走线为什么不能走直角?
涂鸦荣获IoT云平台第一股 物联网平台终于要登上更大的舞台
种子置床设备的设计结构是怎样的,它的使用效果如何
借力新像素结构设计 AMOLED挑战QHD画质
微软的Face API成Laugh Battle比赛的裁判
金士顿新款U.2 SSD发布,随机写入速度最高为210k IOPS
影响变压器套管局部放电的因素
拥抱矿山智能化未来,实现“穿西装打领带”的采矿梦想
介绍下信号反射的过程与反弹图
温度变送器精度等级_温度变送器选型
创想焊缝跟踪系统在尔必地机器人自适应焊接中的应用案例
凤凰科技发布最新变革SecureCore Tiano(SCT)产品