作者:刘鑫
容器类,望文生义便是存储的类,用于存储各种数据类型的元素,并具有一系列处理数据元素的办法。在 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 开发结构的容器类开发出更多高性能的运用。