# 2.7:高性能容器类
容器类,顾名思义就是存储的类,用于存储各种数据类型的元素并提供一系列处理数据元素的方法。ArkUI开发框架提供了线性和非线性两类容器类,这些容器类采用了类似静态的语言来实现,它们通过对存储位置以及属性的限制,让每种类型的数据都能在完成自身功能的基础上剪除冗余分支,保证了数据的高效访问,提升了应用的性能。本章将为大家介绍ArkUI开发框架中容器类的各种类型以及相关 API 的使用。
# 2.7.1:线性容器类
线性容器类包括 List
、 ArrayList
、 LinkedList
、 Vector
、 Deque
、 Queue
、 Stack
七种,底层主要通过数组实现,线性容器类API充分考虑了数据访问的速度,实现了运行时(Runtime)通过一条指令就可以完成增删改查等操作。
List
List
可用来构造一个单向链表对象,即只能通过头结点开始访问到尾节点。List
依据泛型定义,在内存中的存储位置可以是不连续的。可以通过 get / set 等接口对存储的元素进行修改,List
进行增、删、改、查操作的相关 API 如下:declare class List<T> { constructor(); length: number; add(element: T): boolean; get(index: number): T; has(element: T): boolean; getIndexOf(element: T): number; removeByIndex(index: number): T; remove(element: T): boolean; getLastIndexOf(element: T): number; forEach(callbackfn: (value: T, index?: number, List?: List<T>) => void, thisArg?: Object): void; convertToArray(): Array<T>; isEmpty(): boolean; [Symbol.iterator](): IterableIterator<T>; // 省略部分API }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19简单样例如下所示:
import List from '@ohos.util.List' // 导入List模块 let list = new List(); // 创建一个list list.add("a"); // 添加元素 list.add(1); // 添加元素 print(list[0]); // 访问元素 print(list.get(0)); // 访问元素
1
2
3
4
5
6
7
8ArrayList
ArrayList
即动态数组,可用来构造全局的数组对象。ArrayList
依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为10,并支持动态扩容,每次扩容大小为原始容量的 1.5 倍。ArrayList
进行增、删、改、查操作的相关 API 如下:declare class ArrayList<T> { constructor(); length: number; add(element: T): boolean; insert(element: T, index: number): void; has(element: T): boolean; getIndexOf(element: T): number; removeByIndex(index: number): T; remove(element: T): boolean; getLastIndexOf(element: T): number; removeByRange(fromIndex: number, toIndex: number): void; replaceAllElements(callbackfn: (value: T, index?: number, arrlist?: ArrayList<T>) => T, thisArg?: Object): void; forEach(callbackfn: (value: T, index?: number, arrlist?: ArrayList<T>) => void, thisArg?: Object): void; sort(comparator?: (firstValue: T, secondValue: T) => number): void; clear(): void; isEmpty(): boolean; // 省略部分API }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22简单样例如下所示:
import ArrayList from '@ohos.util.ArrayList' // 导入ArrayList模块 let arrayList = new ArrayList(); // 创建一个arrayList arrayList.add("a"); // 添加元素 arrayList.add(1); // 增加元素 print(arrayList[0]); // 访问元素 arrayList[0] = "one"; // 修改元素 print(arrayList[0]); // 访问元素
1
2
3
4
5
6
7
8LinkedList
LinkedList
可用来构造一个双向链表对象,可以在某一节点向前或者向后遍历 List ,LinkedList
依据泛型定义,在内存中的存储位置可以是不连续的。可以通过 get/set 等接口对存储的元素进行修改,LinkedList
进行增、删、改、查操作的相关 API 如下:declare class LinkedList<T> { constructor(); length: number; add(element: T): boolean; insert(index: number, element: T): void; get(index: number): T; addFirst(element: T): void; removeFirst(): T; removeLast(): T; has(element: T): boolean; getIndexOf(element: T): number; removeByIndex(index: number): T; remove(element: T): boolean; removeFirstFound(element: T): boolean; removeLastFound(element: T): boolean; getLastIndexOf(element: T): number; getFirst(): T; getLast(): T; set(index: number, element: T): T; forEach(callbackfn: (value: T, index?: number, LinkedList?: LinkedList<T>) => void, thisArg?: Object): void; clear(): void; [Symbol.iterator](): IterableIterator<T>; // 省略部分API }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27简单样例如下所示:
import LinkedList from '@ohos.util.LinkedList'; // 导入LinkedList模块 let linkedList = new LinkedList(); // 创建一个arrayList linkedList.add("a"); // 添加元素 linkedList.add(1); // 增加元素 print(linkedList[0]); // 访问元素 linkedList.set(0, "one"); // 修改元素 print(linkedList.get(0)); // 访问元素
1
2
3
4
5
6
7
8Vector
Vector
是指连续存储结构,可用来构造全局的数组对象。Vector
依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为 10,并支持动态扩容,每次扩容大小为原始容量的 2 倍。由于Vector
扩容速度高于ArrayList
,所以适用于数据添加比较频繁的场景。Vector
在支持操作符访问的基础上,还增加了 get/set 接口,提供更为完善的校验及容错机制,满足用户不同场景下的需求。Vector
进行增、删、改、查操作的相关 API 如下:declare class Vector<T> { constructor(); length: number; add(element: T): boolean; insert(element: T, index: number): void; get(index: number): T; getIndexOf(element: T): number; getFirstElement(): T; getLastElement(): T; removeByIndex(index: number): T; remove(element: T): boolean; set(index: number, element: T): T; getLastIndexOf(element: T): number; getLastIndexFrom(element: T, index: number): number; getIndexFrom(element: T, index: number): number; removeByRange(fromIndex: number, toIndex: number): void; forEach(callbackfn: (value: T, index?: number, vector?: Vector<T>) => void, thisArg?: Object): void; sort(comparator?: (firstValue: T, secondValue: T) => number): void; subVector(fromIndex: number, toIndex: number): Vector<T>; clear(): void; getCapacity(): number; isEmpty(): boolean; copyToArray(array: Array<T>): void; [Symbol.iterator](): IterableIterator<T>; // 省略部分API }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29简单样例如下所示:
import Vector from '@ohos.util.Vector' // 导入Vector模块 let vector = new Vector(); // 创建一个vector vector.add("a"); // 添加元素 let b = [1, 2, 3]; vector.add(b); // 添加元素 vector.add(false); // 增加元素 print(vector[0]); // 访问元素 print(vector.getFirstElement()); // 访问元素
1
2
3
4
5
6
7
8Queue
Queue
可用来构造队列对象,存储元素遵循先进先出的规则。Queue
依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为 8,并支持动态扩容,每次扩容大小为原始容量的 2 倍。Queue
底层采用循环队列实现,入队及出队操作效率都比较高。Queue
进行增、删、改、查操作的相关 API 如下:declare class Queue<T> { constructor(); length: number; add(element: T): boolean; getFirst(): T; pop(): T; forEach(callbackfn: (value: T, index?: number, Queue?: Queue<T>) => void, thisArg?: Object): void; [Symbol.iterator](): IterableIterator<T>; }
1
2
3
4
5
6
7
8
9
10简单样例如下所示:
import Queue from '@ohos.util.Queue'; let queue = new Queue<string>(); queue.add("test"); print(queue.getFirst()); print(queue.pop());
1
2
3
4
5
6Deque
Deque
可用来构造双端队列对象,存储元素遵循先进先出的规则,双端队列可以分别从对头或者队尾进行访问。Deque
依据泛型定义,要求存储位置是一片连续的内存空间,其初始容量大小为 8,并支持动态扩容,每次扩容大小为原始容量的 2 倍。Deque
底层采用循环队列实现,入队及出队操作效率都比较高。Deque
进行增、删、改、查操作的相关 API 如下:declare class Deque<T> { constructor(); length: number; insertFront(element: T): void; insertEnd(element: T): void; has(element: T): boolean; getFirst(): T; getLast(): T; popFirst(): T; popLast(): T; forEach(callbackfn: (value: T, index?: number, deque?: Deque<T>) => void, thisArg?: Object): void; [Symbol.iterator](): IterableIterator<T>; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14简单样例如下所示:
// Deque import Deque from '@ohos.util.Deque' // 导入Deque模块 let deque = new Deque; // 创建一个deque deque.insertFront("a"); // 添加元素 deque.insertFront(1); // 增加元素 print(deque[0]); // 访问元素 deque[0] = "one"; // 修改元素 print(deque[0]); // 访问元素
1
2
3
4
5
6
7
8
9Stack
Stack
可用来构造栈对象,存储元素遵循后进先出的规则。Stack
依据泛型定义,要求存储位置是一片连续的内存空间,初始容量大小为 8,并支持动态扩容,每次扩容大小为原始容量的 1.5 倍。Stack
底层基于数组实现,入栈出栈均从数组的一端操作,Stack
进行增、删、改、查操作的相关 API 如下:declare class Stack<T> { constructor(); length: number; isEmpty(): boolean; peek(): T; pop(): T; push(item: T): T; locate(element: T): number; forEach(callbackfn: (value: T, index?: number, stack?: Stack<T>) => void, thisArg?: Object): void; [Symbol.iterator](): IterableIterator<T>; }
1
2
3
4
5
6
7
8
9
10
11
12简单样例如下所示:
import Stack from '@ohos.util.Stack' // 导入Stack模块 let stack = new Stack(); // 创建一个stack stack.push("a"); // 添加元素 stack.push(1); // 增加元素 print(stack[0]); // 访问元素 stack.pop(); // 弹出元素 print(stack.length); // 访问容量
1
2
3
4
5
6
7
8
# 2.7.2:非线性容器类
非线性容器类包括 HashMap
、 HashSet
、 TreeMap
、 TreeSet
、 LightWeightMap
、 LightWeightSet
、 PlainArray
七种,底层通过 hash 或者红黑树实现,非线性容器类中的 key
及 value
的类型均满足 ECMA 标准。
HashMap
HashMap
可用来存储具有关联关系的 key-value 键值对集合,存储元素中 key 是唯一的,每个 key 会对应一个 value 值。HashMap
依据泛型定义,集合中通过 key 的 hash 值确定其存储位置,从而快速找到键值对。HashMap
的初始容量大小为 16,并支持动态扩容,每次扩容大小为原始容量的 2 倍。HashMap
底层基于HashTable
实现,冲突策略采用链地址法。HashMap
进行增、删、改、查操作的相关 API 如下:declare class HashMap<K, V> { constructor(); length: number; isEmpty(): boolean; hasKey(key: K): boolean; hasValue(value: V): boolean; get(key: K): V; setAll(map: HashMap<K, V>): void; set(key: K, value: V): Object; remove(key: K): V; clear(): void; keys(): IterableIterator<K>; values(): IterableIterator<V>; replace(key: K, newValue: V): boolean; forEach(callbackfn: (value?: V, key?: K, map?: HashMap<K, V>) => void, thisArg?: Object): void; entries(): IterableIterator<[K, V]>; [Symbol.iterator](): IterableIterator<[K, V]>; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19简单样例如下所示:
import HashMap from '@ohos.util.HashMap' // 导入HashMap模块 let hashMap = new HashMap(); // 创建一个hashMap hashMap.set("a", 123); // 添加元素 hashMap.set(4, 123); // 增加元素 print(hashMap.hasKey(4)); // 判断是否含有某元素 print(hashMap.get("a")); // 访问元素
1
2
3
4
5
6
7HashSet
HashSet
可用来存储一系列值的集合,存储元素中 value 是唯一的。依据泛型定义。集合中通过 value 的 hash 值确定其存储位置,从而快速找到该值。HashSet
初始容量大小为 16,支持动态扩容,每次扩容大小为原始容量的 2 倍。value 的类型满足 ECMA 标准中要求的类型。HashSet
底层基于HashTable
实现,冲突策略采用链地址法。HashSet
进行增、删、改、查操作的相关 API 如下:declare class HashSet<T> { constructor(); length: number; isEmpty(): boolean; has(value: T): boolean; add(value: T): boolean; remove(value: T): boolean; clear(): void; forEach(callbackfn: (value?: T, key?: T, set?: HashSet<T>) => void, thisArg?: Object): void; values(): IterableIterator<T>; entries(): IterableIterator<[T, T]>; [Symbol.iterator](): IterableIterator<T>; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14简单样例如下所示:
import HashSet from '@ohos.util.HashSet'; let hashSet = new HashSet<string>(); hashSet.add("test"); hashSet.remove("test"); print(hashSet.values().next());
1
2
3
4
5
6TreeMap
TreeMap
可用来存储具有关联关系的 key-value 键值对集合,存储元素中 key 是唯一的,每个 key 会对应一个 value 值。TreeMap
依据泛型定义,集合中的 key 值是有序的,TreeMap
的底层是一棵二叉树,可以通过树的二叉查找快速地找到键值对。key 的类型满足 ECMA 标准中要求的类型。TreeMap
中的键值是有序存储的。TreeMap
底层基于红黑树实现,可以进行快速地插入和删除。TreeMap
进行增、删、改、查操作的相关 API 如下:declare class TreeMap<K, V> { constructor(comparator?: (firstValue: K, secondValue: K) => boolean); length: number; isEmpty(): boolean; hasKey(key: K): boolean; hasValue(value: V): boolean; get(key: K): V; getFirstKey(): K; getLastKey(): K; setAll(map: TreeMap<K, V>): void; set(key: K, value: V): Object; remove(key: K): V; clear(): void; getLowerKey(key: K): K; getHigherKey(key: K): K; keys(): IterableIterator<K>; values(): IterableIterator<V>; replace(key: K, newValue: V): boolean; forEach(callbackfn: (value?: V, key?: K, map?: TreeMap<K, V>) => void, thisArg?: Object): void; entries(): IterableIterator<[K, V]>; [Symbol.iterator](): IterableIterator<[K, V]>; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23简单样例如下所示:
import TreeMap from '@ohos.util.TreeMap' // 导入TreeMap模块 let treeMap = new TreeMap(); // 创建一个treeMap treeMap.set("a", 123); // 添加元素 treeMap.set("6", 356); // 增加元素 print(treeMap.get("a")); // 访问元素 print(treeMap.getFirstKey("a")); // 访问首元素 print(treeMap.getLastKey("a")); // 访问尾元素
1
2
3
4
5
6
7
8TreeSet
TreeSet
可用来存储一系列值的集合,存储元素中 value 是唯一的。TreeSet
依据泛型定义,集合中的 value 值是有序的,TreeSet
的底层是一棵二叉树,可以通过树的二叉查找快速地找到该 value 值,value 的类型满足 ECMA 标准中要求的类型。TreeSet
底层基于红黑树实现,可以进行快速地插入和删除。TreeSet
进行增、删、改、查操作的相关 API 如下:declare class TreeSet<T> { constructor(comparator?: (firstValue: T, secondValue: T) => boolean) length: number; isEmpty(): boolean; has(value: T): boolean; add(value: T): boolean; remove(value: T): boolean; clear(): void; getFirstValue(): T; getLastValue(): T; getLowerValue(key: T): T; getHigherValue(key: T): T; popFirst(): T; popLast(): T; forEach(callbackfn: (value?: T, key?: T, set?: TreeSet<T>) => void, thisArg?: Object): void; values(): IterableIterator<T>; entries(): IterableIterator<[T, T]>; [Symbol.iterator](): IterableIterator<T>; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20简单样例如下所示:
import TreeSet from '@ohos.util.TreeSet'; let treeSet = new TreeSet<string>(); treeSet.add("test"); treeSet.remove("test") print(treeSet.getFirstValue()); print(treeSet.getLowerValue('test'));
1
2
3
4
5
6
7LightWeightMap
LigthWeightMap
可用来存储具有关联关系的 key-value 键值对集合,存储元素中 key 是唯一的,每个 key 会对应一个 value 值。LigthWeightMap
依据泛型定义,采用更加轻量级的结构,集合中的 key 值的查找依赖于 hash 值以及二分查找算法,通过一个数组存储 hash 值,然后映射到其他数组中的 key 值以及 value 值,key 的类型满足 ECMA 标准中要求的类型。初始默认容量大小为 8,每次扩容大小为原始容量的 2 倍。LigthWeightMap
底层标识唯一 key 通过 hash 实现,其冲突策略为线性探测法,查找策略基于二分查找法。LigthWeightMap
进行增、删、改、查操作的相关 API 如下:declare class LightWeightMap<K, V> { constructor(); length: number; hasAll(map: LightWeightMap<K, V>): boolean; hasKey(key: K): boolean; hasValue(value: V): boolean; increaseCapacityTo(minimumCapacity: number): void; entries(): IterableIterator<[K, V]>; get(key: K): V; getIndexOfKey(key: K): number; getIndexOfValue(value: V): number; isEmpty(): boolean; getKeyAt(index: number): K; keys(): IterableIterator<K>; setAll(map: LightWeightMap<K, V>): void; set(key: K, value: V): Object; remove(key: K): V; removeAt(index: number): boolean; clear(): void; setValueAt(index: number, newValue: V): boolean; forEach(callbackfn: (value?: V, key?: K, map?: LightWeightMap<K, V>) => void, thisArg?: Object): void; [Symbol.iterator](): IterableIterator<[K, V]>; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24简单样例如下所示:
import LightWeightMap from '@ohos.util.LightWeightMap'// 导入LightWeightMap模块 let lightWeightMap = new LightWeightMap(); // 创建一个lightWeightMap lightWeightMap.set("x", 123); // 添加元素 lightWeightMap.set("8", 356); // 增加元素 print(lightWeightMap.get("a")); // 访问元素 print(lightWeightMap.get("x")); // 访问元素 print(lightWeightMap.getIndexOfKey("8")); // 访问元素
1
2
3
4
5
6
7
8LightWeightSet
LigthWeightSet
可用来存储一系列值的集合,存储元素中 value 是唯一的。LigthWeightSet
依据泛型定义,采用更加轻量级的结构,初始默认容量大小为 8,每次扩容大小为原始容量的 2 倍。集合中的 value 值的查找依赖于 hash 以及二分查找算法,通过一个数组存储 hash 值,然后映射到其他数组中的 value 值,value 的类型满足 ECMA 标准中要求的类型。LigthWeightSet
底层标识唯一 value 基于 hash 实现,其冲突策略为线性探测法,查找策略基于二分查找法。LigthWeightSet
进行增、删、改、查操作的相关 API 如下:declare class LightWeightSet<T> { constructor(); length: number; add(obj: T): boolean; addAll(set: LightWeightSet<T>): boolean; hasAll(set: LightWeightSet<T>): boolean; has(key: T): boolean; equal(obj: Object): boolean; increaseCapacityTo(minimumCapacity: number): void; getIndexOf(key: T): number; remove(key: T): T; removeAt(index: number): boolean; clear(): void; forEach(callbackfn: (value?: T, key?: T, set?: LightWeightSet<T>) => void, thisArg?: Object): void; [Symbol.iterator](): IterableIterator<T>; // 省略部分API }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20简单样例如下所示:
import LightWeightSet from '@ohos.util.LightWeightSet'; let lightWeightSet = new LightWeightSet<String>(); lightWeightSet.add("test"); lightWeightSet.remove("test"); print(lightWeightSet.getValueAt(0)) print(lightWeightSet.getIndexOf("test"))
1
2
3
4
5
6
7PlainArray
PlainArray
可用来存储具有关联关系的键值对集合,存储元素中 key 是唯一的,并且对于PlainArray
来说,其 key 的类型为number
类型。每个 key 会对应一个 value 值,类型依据泛型的定义,PlainArray
采用更加轻量级的结构,集合中的 key 值的查找依赖于二分查找算法,然后映射到其他数组中的 value 值。初始默认容量大小为 16,每次扩容大小为原始容量的 2 倍。PlainArray
的查找策略基于二分查找法。PlainArray
进行增、删、改、查操作的相关 API 如下:declare class PlainArray<T> { constructor(); length: number; add(key: number, value: T): void; clear(): void; clone(): PlainArray<T>; has(key: number): boolean; get(key: number): T; getIndexOfKey(key: number): number; getIndexOfValue(value: T): number; isEmpty(): boolean; getKeyAt(index: number): number; remove(key: number): T; removeAt(index: number): T; removeRangeFrom(index: number, size: number): number; setValueAt(index: number, value: T): void; getValueAt(index: number): T; forEach(callbackfn: (value: T, index?: number, PlainArray?: PlainArray<T>) => void, thisArg?: Object): void; [Symbol.iterator](): IterableIterator<[number, T]>; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21简单样例如下所示:
import PlainArray from '@ohos.util.PlainArray' // 导入PlainArray模块 let plainArray = new PlainArray(); // 创建一个plainArray plainArray.add(1, "sdd"); // 添加元素 plainArray.add(2, "sff"); // 添加元素 print(plainArray.get(1)); // 访问元素 print(plainArray.getKeyAt(1)); // 访问元素
1
2
3
4
5
6
7
# 2.7.3:小结
本章简单介绍了ArkUI开发框架提供的高性能集合类,在项目开发中合理的利用这些集合可以有效的提升应用性能,本章节部分摘选了华为专家的文章 (opens new window)。