作者:liuxin,华为高级工程师
容器类,顾名思义就是存储的类,用于存储各种数据类型的元素,并具备一系列解决数据元素的办法。在方舟开发框架中,容器类采纳了相似动态的语言来实现,并通过NAPI框架对外提供。通过对存储地位以及属性的限度,让每种类型的数据都能在实现本身性能的根底上剪除冗余分支,保障了数据的高效拜访,晋升了利用的性能。本期,咱们将为大家介绍方舟开发框架中容器类的各种类型以及相干API的应用。

一、容器类API介绍

在方舟开发框架中,提供了线性和非线性两类容器类,共14种,每种容器都有本身的个性及应用场景。上面,咱们将为大家一一道来。
1

线性容器类

线性容器类底层次要通过数组实现,包含ArrayList、Vector、List、LinkedList、Deque、Queue、Stack七种。线性容器类API,充分考虑了数据拜访的速度,实现了运行时(Runtime)通过一条指令就能够实现增删改查等操作。

  1. ArrayList

ArrayList即动静数组,可用来结构全局的数组对象。ArrayList根据泛型定义,要求存储地位是一片间断的内存空间,初始容量大小为10,并反对动静扩容,每次扩容大小为原始容量的1.5倍。ArrayList进行增、删、改、查操作的相干API如下:

  1. Vector

Vector 是指间断存储构造,可用来结构全局的数组对象。Vector根据泛型定义,要求存储地位是一片间断的内存空间,初始容量大小为10,并反对动静扩容,每次扩容大小为原始容量的2倍。
因为Vector扩容速度高于ArrayList,所以实用于数据增加比拟频繁的场景。Vector在反对操作符拜访的根底上,还减少了get/set接口,提供更为欠缺的校验及容错机制,满足用户不同场景下的需要。Vector进行增、删、改、查操作的相干API如下:

  1. List

List可用来结构一个单向链表对象,即只能通过头结点开始拜访到尾节点。List根据泛型定义,在内存中的存储地位能够是不间断的。
能够通过get/set等接口对存储的元素进行批改,List进行增、删、改、查操作的相干API如下:

  1. LinkedList

LinkedList可用来结构一个双向链表对象,能够在某一节点向前或者向后遍历List。LinkedList根据泛型定义,在内存中的存储地位能够是不间断的。
能够通过get/set等接口对存储的元素进行批改,LinkedList进行增、删、改、查操作的相干API如下:

  1. Queue

Queue可用来结构队列对象,存储元素遵循先进先出的规定。Queue根据泛型定义,要求存储地位是一片间断的内存空间,初始容量大小为8,并反对动静扩容,每次扩容大小为原始容量的2倍。Queue底层采纳循环队列实现,入队及出队操作效率都比拟高。Queue进行增、删、改、查操作的相干API如下:

  1. Deque

Deque可用来结构双端队列对象,存储元素遵循先进先出的规定,双端队列能够别离从对头或者队尾进行拜访。Deque根据泛型定义,要求存储地位是一片间断的内存空间,其初始容量大小为8,并反对动静扩容,每次扩容大小为原始容量的2倍。Deque底层采纳循环队列实现,入队及出队操作效率都比拟高。Deque进行增、删、改、查操作的相干API如下:

  1. Stack

Stack可用来结构栈对象,存储元素遵循后进先出的规定。Stack根据泛型定义,要求存储地位是一片间断的内存空间,初始容量大小为8,并反对动静扩容,每次扩容大小为原始容量的1.5倍。Stack底层基于数组实现,入栈出栈均从数组的一端操作,Stack进行增、删、改、查操作的相干API如下:

2、非线性容器类

非线性容器类底层通过hash或者红黑树实现,包含HashMap、HashSet、TreeMap、TreeSet、LightWeightMap、LightWeightSet、PlainArray七种。非线性容器类中的key及value的类型均满足ECMA规范。

  1. HashMap

HashMap可用来存储具备关联关系的key-value键值对汇合,存储元素中key是惟一的,每个key会对应一个value值。HashMap根据泛型定义,汇合中通过key的hash值确定其存储地位,从而疾速找到键值对。HashMap的初始容量大小为16,并反对动静扩容,每次扩容大小为原始容量的2倍。HashMap底层基于HashTable实现,抵触策略采纳链地址法。HashMap进行增、删、改、查操作的相干API如下:

  1. HashSet

HashSet可用来存储一系列值的汇合,存储元素中value是惟一的。根据泛型定义。汇合中通过value的hash值确定其存储地位,从而疾速找到该值。HashSet初始容量大小为16,反对动静扩容,每次扩容大小为原始容量的2倍。value的类型满足ECMA规范中要求的类型。HashSet底层基于HashTable实现,抵触策略采纳链地址法。HashSet进行增、删、改、查操作的相干API如下:

  1. TreeMap

TreeMap可用来存储具备关联关系的key-value键值对汇合,存储元素中key是惟一的,每个key会对应一个value值。TreeMap根据泛型定义,汇合中的key值是有序的,TreeMap的底层是一棵二叉树,能够通过树的二叉查找疾速的找到键值对。key的类型满足ECMA规范中要求的类型。TreeMap中的键值是有序存储的。TreeMap底层基于红黑树实现,能够进行疾速的插入和删除。TreeMap进行增、删、改、查操作的相干API如下:

  1. TreeSet

TreeSet可用来存储一系列值的汇合,存储元素中value是惟一的。TreeSet根据泛型定义,汇合中的value值是有序的,TreeSet的底层是一棵二叉树,能够通过树的二叉查找疾速的找到该value值,value的类型满足ECMA规范中要求的类型。TreeSet中的值是有序存储的。TreeSet底层基于红黑树实现,能够进行疾速的插入和删除。TreeSet进行增、删、改、查操作的相干API如下:

  1. LightWeightMap

LigthWeightMap可用来存储具备关联关系的key-value键值对汇合,存储元素中key是惟一的,每个key会对应一个value值。LigthWeightMap根据泛型定义,采纳更加轻量级的构造,汇合中的key值的查找依赖于hash值以及二分查找算法,通过一个数组存储hash值,而后映射到其余数组中的key值以及value值,key的类型满足ECMA规范中要求的类型。
初始默认容量大小为8,每次扩容大小为原始容量的2倍。LigthWeightMap底层标识惟一key通过hash实现,其抵触策略为线性探测法,查找策略基于二分查找法。LigthWeightMap进行增、删、改、查操作的相干API如下:

  1. LightWeightSet

LigthWeightSet可用来存储一系列值的汇合,存储元素中value是惟一的。LigthWeightSet根据泛型定义,采纳更加轻量级的构造,初始默认容量大小为8,每次扩容大小为原始容量的2倍。汇合中的value值的查找依赖于hash以及二分查找算法,通过一个数组存储hash值,而后映射到其余数组中的value值,value的类型满足ECMA规范中要求的类型。
LigthWeightSet底层标识惟一value基于hash实现,其抵触策略为线性探测法,查找策略基于二分查找法。LigthWeightSet进行增、删、改、查操作的相干API如下:

  1. PlainArray

PlainArray可用来存储具备关联关系的键值对汇合,存储元素中key是惟一的,并且对于PlainArray来说,其key的类型为number类型。每个key会对应一个value值,类型根据泛型的定义,PlainArray采纳更加轻量级的构造,汇合中的key值的查找依赖于二分查找算法,而后映射到其余数组中的value值。
初始默认容量大小为16,每次扩容大小为原始容量的2倍。PlainArray的查找策略基于二分查找法。PlainArray进行增、删、改、查操作的相干API如下:

二、容器类的实现

上面咱们将以ArrayList为例,为大家介绍,容器类的实现。包含容器类的初始化、容器类的接口调用、容器类对象模型的构建以及拦截器解决。
1.容器类初始化

在方舟开发框架中,通过NAPI的对立框架对外层提供容器类。上面,咱们将以ArrayList为例,介绍基于NAPI的容器类的加载。如下图所示,是容器类初始化流程,在NAPI加载的过程中,会通过ArkPrivate.Load接口加载对应的容器类。ArrayList在引擎中会初始化Constructor以及Prototype并返回,最初利用侧能够取得该容器类并应用。


图1 容器类初始化流程

2.容器类接口调用

在方舟开发框架中,容器类API的调用流程如图2所示,用户先通过new ArrayList进入引擎失去对应的arraylist对象,而后能够通过add接口向对象中增加元素,元素最终会增加到一片和该arraylist绑定的内存空间。能够通过[]操作符进行元素获取,对于容器类而言,引擎会间接通过疾速门路拜访到元素存储地位,返回该值。


图2 容器类API的调用流程

3.容器类对象模型

在方舟开发框架中,结构容器类对象模型的流程如下图所示,在运行时禁止再向对象上增加Properties属性,ArrayList借用对象模型中的elements地位存储元素。


图3 容器类对象模型的结构流程

实现阐明:通过elements存储数组元素,Length为数组中元素个数,数组Capatity能够通过elements的长度获取。

扩容策略:ArrayList –> 1.5倍

初始调配容量:ArrayList -> 10
(注:TS中的实现,扩容策略及初始调配容量不感知)

4.拦截器解决

拦截器解决,是指通过禁止掉一些影响对象行为的操作,比方delete、setPrototype等,在运行时(Runtime)保护一个高效的容器类对象。如图4所示,以ArrayList为例,ArkCompiler外部拦挡的操作次要波及DeleteProperty、DefineProperty、GetProperty、SetPrototype、GetOwnPropertyKeys、HasProperty等操作限度数组的holy增加,以及更改属性的attributes等操作,保障了不须要做JSArray必须做的holy 判断、writable 判断等操作。


图4 拦截器解决

三、容器类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)); // 拜访元素

至此以上就是本期全部内容,期待宽广开发者通过方舟开发框架的容器类开发出更多高性能的利用。