前言
你是否遇到过需要快速去重或高效查找元素的场景?比如统计一组用户ID的唯一性,或是检查某个关键词是否已存在?在Dart中,Set正是为解决这类问题而生的利器。与List不同,Set天生具备元素唯一性和无序性,其底层基于哈希表实现,使得查找、插入和删除操作的时间复杂度接近O(1),性能优势显著。相信你已经很期待Set利器的使用方式了,那接下来就跟随我们一起走近Set,掌握Set这把瑞士军刀。
一、基本概念
1.1、定义
集合(Set)又称为无序集合,是一个无序且不允许重复的元素集合。和数学中集合概念一样其具有数学中集合的特点和操作(并、交、差)。
1.2、特点
- 无序:集合中的元素没有按照一定的顺序进行排列。
- 不可重复(唯一性):和列表不同,集合(Set)中的元素不能重复。
1.3、泛型支持
Dart中集合(Set)和列表一样可以支持不同的数据类型。通过动态类型声明。
二、创建和初始化
2.1、直接创建
通过大括号({})直接创建。
示例:
void main() {
Set<int> intSet = {2,23,3,14,6,90};
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
}
2.2、使用构造函数创建
<String>{}:创建空集合。Set<int>.from():创建具有初始值的集合。
示例:
void main() {
Set<String> emptySet = <String>{};
Set<int> fromSet = Set<int>.from([2,23,3,14,6,90]);
}
2.3、使用Set.of创建
Set.of()可以从任何可迭代对象创建集合(Set)。
示例:
void main() {
Set<int> ofSet = Set.of([2,23,3,14,6,90]);
}
三、不可变集合
Dart中支持创建一个不可变的集合,使用Set.unmodifiable()创建。
示例:
void main() {
Set<int> unmodifiableSet = Set.unmodifiable([2,23,3,14,6,90]);
// 尝试添加内容。
unmodifiableSet.add(1200); // Unsupported operation: Cannot change an unmodifiable set
}
运行时报错:
四、常用属性和方法
4.1、常用属性
- length:获取集合长度。
- isEmpty:判断是否为空集合,为空集合输出true,否则false。
- first:获取集合第一个元素。
- last:获取集合最后一个元素。
示例:
void main() {
Set<int> intSet = {2,23,3,14,6,90};
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
print(intSet.length); // 输出:6
print(intSet.isEmpty); // 输出:false
print(intSet.first); // 输出:2
print(intSet.last); // 输出:90
}
4.2、常用方法
- contains():判断集合中是否包含某元素,结果为布尔类型。
- union():集合操作,并。
- intersection():集合操作,交。
- difference():集合操作,差。
- 高阶函数:map()、where()、any()、every()等。
注意:union()、intersection()、difference()会创建一个新集合。
示例:
void main() {
Set<int> intSet = {2,23,3,14,6,90};
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
Set<int> intSetA = {1,5,9};
Set<int> intSetB = {2,5,8};
print(intSetA.contains(1200)); // 输出:false
// 并集
print(intSetA.union(intSetB));// 输出:{1, 5, 9, 2, 8}
// 交集
print(intSetA.intersection(intSetB)); // 输出:{5}
// 差集
print(intSetA.difference(intSetB)); // 输出:{1, 9}
// 查找元素中所有大于20的元素。
Set<int> whereSet = intSet.where((element) => element>20).toSet();
print(whereSet); // 输出:{23, 90}
// 判断集合中是否有大于五十的数返回bool类型。
bool hasAnyBool = intSet.any((element) => element > 50);
print(hasAnyBool);// 输出:true
// 判断集合中是否所有元素都大于五十,返回bool类型。
bool hasEveryBool = intSet.every((element) => element > 50);
print(hasEveryBool);// 输出:false
}
五、访问元素
集合(Set)可通过遍历的方式访问元素。其与列表不同,集合是无序的,不支持所有关于下标的操作。
5.1、遍历
将集合中的所有元素依次访问一遍。
- 使用for循环遍历(转换为列表遍历)。
- 使用for-in遍历。
- 使用高阶函数 forEach() 遍历。
示例: for循环遍历
void main() {
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
List<dynamic> dynamicList = dynamicSet.toList(); // 转换为列表进行遍历
for (int i=0;i<dynamicList.length;i++){
print(dynamicList[i]);
}
}
示例: for-in循环遍历
void main() {
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
for (var element in dynamicSet){
print(element);
}
}
示例: 高阶函数forEach()遍历
void main() {
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
dynamicSet.forEach((element) => print(element));
}
六、添加元素
- add():添加单个元素。
- addAll():批量添加元素。
注意:add()、addAll()都是原地添加,即在原来基础上进行添加。
示例:
void main() {
Set<int> intSet = {2,23,3,14,6,90};
intSet.add(1200); // 原地操作,在原来的基础上进行添加。
print(intSet); // 输出:{2, 23, 3, 14, 6, 90, 1200}
intSet.addAll([1,2,3,1899,1899]);
print(intSet); // 去除重复元素,输出:{2, 23, 3, 14, 6, 90, 1200, 1, 1899}
}
七、修改元素
Dart集合(Set)不支持通过下标进行元素的访问和修改,这就意味着我们不能通过如同列表那样去修改元素。当然也可以将其转为列表(List)再进行修改,但通常我们采取的是移除要修改的元素后再添加修改后的元素。
示例:
void main() {
Set<int> intSet = {2,23,3,14,6,90};
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
// 修改元素apple为1200
dynamicSet.remove('apple'); // 1、移除元素apple
print(dynamicSet); // 输出:{23, true, 12.5, peach, pear}
dynamicSet.add(1200); // 2、添加元素1200
print(dynamicSet); // 输出:{23, true, 12.5, peach, pear, 1200}
}
八、移除元素
- remove():移除单个元素。
- removeAll():移除多个元素。
- removeWhere():移除符合条件的元素。
- clear():清空集合。
示例:
void main() {
Set<int> intSet = {2,23,3,14,6,90};
Set<dynamic> dynamicSet = {23,true,'apple',12.5,'peach','pear'};
dynamicSet.remove('apple');
print(dynamicSet); // 输出:{23, true, 12.5, peach, pear}
dynamicSet.removeAll([23,true]);
print(dynamicSet); // 输出:{12.5, peach, pear}
dynamicSet.removeWhere((element) => element==12.5);// 移除等于12.5的元素
print(dynamicSet); // 输出:{peach, pear}
dynamicSet.clear();
print(dynamicSet); // 输出:{}
}
九、总结
本小节归纳总结如下:
| 方法或属性 | |
|---|---|
| 创建和初始化 | 1、使用{}创建。2、 <int>{}创建空集合。3、 Set<int>.from() 4、 Set.of() |
| 不可变集合 | 使用Set.unmodifiable()创建。 |
| 常用属性和方法 | 1、length属性。 2、isEmpty属性。 3、first属性。 4、last属性。 1、 contains()方法。 2、union()方法。 3、intersection()方法。 4、 difference()方法。 5、高阶函数map()等。 |
| 访问元素 | 1、for遍历(转换为列表)。 2、 for-in遍历。3、高阶函数 forEach()遍历。 |
| 添加元素 | 1、add()添加单个元素。 2、 addAll()添加多个元素。 |
| 修改元素 | 1、移除要修改的元素。 2、添加修改后的内容。 |
| 移除元素 | 1、remove()移除单个元素。 2、 removeAll()批量移除元素。3、 removeWhere()移除符合条件的元素。 4、 clear()清空列表。 |