在基础数据类型一篇我们了解了仓颉数组类型,用来表示单一类型的元素构成的有序序列。使用 Array<T> 来表示 Array 类型。T 表示 Array 的元素类型,T 可以是任意类型。
public struct Array<T> {
public const init()
public init(size: Int64, repeat!: T)
public init(size: Int64, initElement: (Int64) -> T)
}
由于Array是结构体类型,所以被定义的数组,不能增删,只能修改,适合不需要增加和删除元素,但需要修改元素的场景。
Collection (不支持并发安全)
collection 包提供了常见数据结构的高效实现、相关抽象的接口的定义以及在集合类型中常用的函数功能。以下常用的数据结构:
| 数据结构 | 功能 |
|---|---|
| ArrayDeque<T> | 基于数组实现的双端循环队列,支持在集合的两端进行元素的插入和删除操作。 |
| ArrayList<T> | 提供可变长度的数组的功能。 |
| ArrayQueue<T> | 基于数组实现的循环队列,只允许在尾部插入元素,在头部删除元素。 |
| ArrayStack<T> | 基于数组实现的栈数据结构。特点是先进后出,只能在顶部进行数据的插入和删除。 |
| HashMap<K, V> | 储键值对,并且可以根据键快速访问值。在需要使用映射关系并且需要快速查找时使用。 |
| HashSet<T> | 基于哈希表实现的集合数据结构,它可以用于快速检索和删除元素,具有高效的插入、删除和查找操作。 |
| LinkedList<T> | 实现双向链表的数据结构。 |
| TreeMap<K, V> | 当需要将元素按照自然顺序或者自定义顺序进行排序时,可以使用。 |
| TreeSet<T> | 基于 TreeMap 实现的有序集合。能自动排序元素,可用于存储不重复且需排序的数据。 |
ArrayList<T>
ArrayList 是一种线性的动态数组,与 Array 不同,它可以根据需要自动调整大小,并且在创建时不需要指定大小。
public class ArrayList<T> <: List<T> {
public init()
public init(capacity: Int64)
public init(size: Int64, initElement: (Int64) -> T)
public init(elements: Collection<T>)
}
| api | 说明 |
|---|---|
| size | 元素个数 |
| capacity | 容量大小 |
| first | 返回第一个元素,如果没有则返回 None |
| last | 返回最后一个元素,如果没有则返回 None |
| of(elements: Array<T>) | 构造一个包含指定数组中所有元素的集合 |
| add(element: T) | 将指定的元素附加到末尾 |
| add(all!: Collection<T>) | 将指定集合中的所有元素附加到末尾 |
| add(element: T, at!: Int64) | 指定位置插入指定元素 |
| add(all!: Collection<T>, at!: Int64) | 从指定位置开始,将指定集合中的所有元素插入 |
| clear() | 删除所有元素 |
| clone() | 浅拷贝 |
| get(index: Int64) | 返回指定位置的元素 |
| getRawArray() | 返回原始数据 |
| isEmpty() | 是否为空 |
| iterator() | 返回迭代器 |
| remove(at!: Int64) | 删除指定位置的元素 |
| remove(range: Range<Int64>) | 删除range范围所包含的所有元素 |
| removeIf(predicate: (T) -> Bool) | 删除满足给定 lambda 表达式或函数的所有元素 |
| reserve(additional: Int64) | 扩容 |
| reverse() | 反转元素的顺序 |
| slice(range: Range<Int64>) | 返回range索引对应的ArrayList<T> |
| toArray() | 返回一个数组 |
| sort<T>(data, stable, descending) | 根据Comparable实现升序或降序排序 |
import std.collection.*
main() {
var array = ArrayList<Int64>()
println(array.size) // 元素个数:0
println(array.capacity) //容量:16
for (i in 0..16) {
array.add(i) //添加0-15
}
println(array.size) // 元素个数:16
println(array.capacity) //容量:16
for (i in 16..32) {
array.add(i) //添加16-31
}
println(array.size) // 元素个数:32
println(array.capacity) //容量:36
array.remove(0..10) //删除下标 0-9 的元素
println(array.size) // 元素个数:22
println(array.capacity) //容量:36
array.clear() //清空
println(array.size) // 元素个数:0
println(array.capacity) //容量:36
var a = ArrayList.of(array)
println(a.toString())
}
HashMap<K, V>
哈希表是一种常用的数据结构,它可以用来快速地查找、插入和删除数据。哈希表的基本原理是将数据映射到一个数组中,这个数组称为哈希表。每个数据元素都有一个对应的哈希值,这个哈希值可以用来确定该元素在哈希表中的位置。
哈希表的特点是快速的查找、插入和删除操作,时间复杂度通常是O(1)。由于哈希表底层的数组大小是动态的,所以哈希表不能保证元素的顺序不可变。
public class HashMap<K, V> <: Map<K, V> where K <: Hashable & Equatable<K> {
public init()
public init(elements: Array<(K, V)>)
public init(elements: Collection<(K, V)>)
public init(capacity: Int64)
public init(size: Int64, initElement: (Int64) -> (K, V))
}
| api | 说明 |
|---|---|
| size | 键值对的个数 |
| capacity | 容量大小 |
| add(key: K, value: V) | 存入键值对,如已有的键,存入新值,返回旧值 |
| add(all!: Collection<(K, V)>) | 按照 elements 的迭代器顺序将新的键值对集合放入,已有的键,该键的值将被新值替换 |
| addIfAbsent(key: K, value: V) | 如果 key 不在,添加指定键值对 key-value。否则不做修改 |
| clear() | 清除所有键值对 |
| clone() | 克隆,返回一个HashMap<K,V> |
| contains(key: K) | 判断是否包含指定键的映射 |
| contains(all!: Collection<K>) | 判断是否包含指定集合中所有键的映射 |
| entryView(key: K) | 如果包含特定键,则返回该键对应的元素的引用视图。否则返回一个空的引用视图。 |
| get(key: K) | 返回指定键映射到的值 |
| isEmpty() | 是否为空 |
| iterator() | 返回 HashMap 的迭代器 |
| keys() | 返回所有的key,并将所有 key 存储在一个 Keys 容器中 |
| remove(all!: Collection<K>) | 删除指定集合中键的映射 |
| remove(key: K) | 删除指定键的映射 |
| removeIf(predicate: (K, V) -> Bool) | 传入 lambda 表达式,如果满足条件,则删除对应的键值对 |
| replace(key: K, value: V) | 指定 key,将其值修改为 value。否则不做修改 |
| reserve(additional: Int64) | 扩容 |
| toArray() | 返回键值对的数组Array<K,V> |
| values() | 返回包含的值,并将所有的 value 存储在一个 Values 容器中 |
import std.collection.*
main() {
var a = HashMap<String, Int64>()
println('初始size:${a.size}') // 0
println('初始容量:${a.capacity}') // 16
a.add('语文',90)
a.add('数学',93)
a.add('英语',96)
a.add('历史',94)
println(a.keys().toArray()) //[语文, 数学, 英语, 历史]
println('语文:${a.get('语文')}') //Some(90)
a.addIfAbsent('语文',99)
println('语文:${a.get('语文')}') //Some(90)
println(a.values().toArray()) //[90, 93, 96, 94]
a.replace('地理', 100)
println(a.contains('地理')) //false
a.removeIf({k,v=>v>90}) //删除 满足 值>90 的键值对
println(a.keys().toArray()) // [语文]
a['语文']=100
println(a['语文']) //100
}
HashSet
使用 HashSet 类型来构造只拥有不重复元素的 Collection。它可以用于快速检索和删除元素,具有高效的插入、删除和查找操作。
public class HashSet<T> <: Set<T> where T <: Hashable & Equatable<T> {
public init()
public init(elements: Collection<T>)
public init(elements: Array<T>)
public init(capacity: Int64)
public init(size: Int64, initElement: (Int64) -> T)
}
| api | 说明 |
|---|---|
| size | 元素个数 |
| capacity | 内部数组容量大小 |
| add(element: T) | 添加元素,如存在,添加失败 |
| add(all!: Collection<T>) | 添加集合中所有元素,如存在,则不添加 |
| clear() | 移除所有元素 |
| clone() | 克隆 |
| contains(element: T) | 是否包含指定元素 |
| contains(all!: Collection<T>) | 是否包含指定collection中的所有元素 |
| isEmpty() | 是否为空 |
| iterator() | 返回迭代器 |
| remove(element: T) | 移除 |
| remove(all!: Collection<T>) | 移除也包含在collection中的元素 |
| removeIf(predicate: (T) -> Bool) | 传入 lambda 表达式,如果满足 true 条件,则删除对应的元素 |
| reserve(additional: Int64) | 扩容 |
| retain(all!: Set<T>) | 保留set中的元素 |
| subsetOf(other: ReadOnlySet<T>) | 检查该集合是否为其他ReadOnlySet的子集 |
| toArray() | 返回一个包含容器内所有元素的数组 |
| &(other: ReadOnlySet<T>) | 交集 |
| |(other: ReadOnlySet<T>) | 并集 |
| -(other: ReadOnlySet<T>) | 差集 |
| ==(that: HashSet<T>) | 两个Set其中包含的元素是否完全相等 |
import std.collection.*
main() {
var a = HashSet<Int64>()
println('初始size:${a.size}') // 0
println('初始容量:${a.capacity}') // 16
a.add(all:[1,3,5,7])
println(a) //[1, 3, 5, 7]
var b = a.clone()
b.add(2)
b.add(4)
b.add(6)
println(a.toArray()) //[1, 3, 5, 7]
println(b.toArray()) //[1, 3, 5, 7, 2, 4, 6]
println(b.contains(all:a)) //true
println(a&b) //[1, 3, 5, 7]
println(b-a) //[2, 4, 6]
println(a|b) //[1, 3, 5, 7, 2, 4, 6]
b.removeIf({v=>v%2==0}) // 删除b中的偶数
println(b) //[1, 3, 5, 7]
}
Iterable<E>
该接口表示可迭代,实现了该接口的类型(通常为容器类型)可以在 for-in 语句中实现迭代,也可以获取其对应的迭代器类型实例,调用 next 函数实现迭代。
public interface Iterable<E> {
func iterator(): Iterator<E>
}
Array、ArrayList、HashSet、HashMap 类型都实现了 Iterable,因此可以将其用在 for-in 或者 while 中。
import std.collection.*
main() {
var a = ArrayList<Int64>([1,3,5,7,9])
for (i in a) {
print(i) // 13579
}
println()
var it = a.iterator()
while (true) {
match (it.next()) {
case Some(i) => print(i) //13579
case None => break
}
}
println()
var it2=a.iterator()
while (let Some(i) <- it2.next()) {
print(i) //13579
}
}
collection.concurrent (并发安全)
本包实现了以下几种并发安全的集合类型
| 数据结构 | 功能 |
|---|---|
| ArrayBlockingQueue<E> | 以数组的形式实现的具有固定大小的有界队列 |
| ConcurrentHashMap<K, V> | 线程安全的哈希表实现,支持高并发的读写操作 |
| ConcurrentLinkedQueue<E> | 提供一个线程安全的队列,可以在多线程环境下安全地进行元素的添加和删除操作 |
| LinkedBlockingQueue<E> | 一种阻塞队列,它支持在队列为空时阻塞获取元素的操作,以及在队列已满时阻塞添加元素的操作 |