仓颉编程入门:集合

在基础数据类型一篇我们了解了仓颉数组类型,用来表示单一类型的元素构成的有序序列。使用 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> 一种阻塞队列,它支持在队列为空时阻塞获取元素的操作,以及在队列已满时阻塞添加元素的操作
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容