共计 6396 个字符,预计需要花费 16 分钟才能阅读完成。
作者:刘鑫
容器类,顾名思义就是存储的类,用于存储各种数据类型的元素,并具备一系列解决数据元素的办法。在 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 呢?本文列举罕用的典型容器的应用示例,包含导入模块、减少元素、拜访元素及批改等操作:
// ArrayList
import 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]);
// Vector
import 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()); // 拜访元素
// Deque
import 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]);
// Stack
import Stack from '@ohos.util.Stack' // 导入 Stack 模块
let stack = new Stack();
stack.push("a");
stack.push(1); // 减少元素
print(stack[0]); // 拜访元素
stack.pop(); // 弹出元素
print(stack.length);
// List
import 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)); // 拜访元素
// HashMap
import 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")); // 拜访元素
// TreeMap
import 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")); // 拜访尾元素
// LightWeightMap
import 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")); // 拜访元素
// PlainArray
import 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 开发框架的容器类开发出更多高性能的利用。