Set(集)
Set 是不重复元素的无序集,它主要关注元素是否在 Set 中,并具有两个特征:
- 唯一性:其元素在 Set 内 是唯一的
- 无序性:通常不能像 List 那样通过下标获取某个元素
对 Set 元素的遍历可以是无序,也可以是某方面有序的:
HashSet是无序的LinkedHashSet按元素的写入顺序遍历- 有序 Set(如
SplayTreeSet),按排序顺序进行遍历
classDiagram Set~E~ <|.. HashSet Set~E~ <|.. LinkedHashSet Set~E~ <|.. SetMixin~E~ SetMixin~E~ <|-- SplayTreeSet~E~: with <<inferface>> Set <<final>> LinkedHashSet <<final>> HashSet <<final>> SplayTreeSet <<mixin>> SetMixin
Set 示例
先看一个简单的例子。
// ex641.dart
void main() {
var fruites = {'Apple', 'Banana'}; // 1
print(fruites.runtimeType); // Output: _Set<String>
print(fruites); // Ouput: {Apple, Banana}
fruites.add('Apple'); // 2
print(fruites); // Ouput: {Apple, Banana}
fruites.add('Cherry'); // 3
print(fruites); // Ouput: {Apple, Banana, Cherry}
print(fruites.length); // 4 Output: 3
}
- 使用字面量声明一个类型为Set
的变量 fruites,它包含两个初始成员 'Apple' 和 'Banana'; - 给
fruites添加一个成员Apple,由于Apple本来就已经在fruitesSet中,因此这行代码执行后fruites的成员依旧只有原来的那两个; - 向
fruites追加一个新的成员Cherry,这样代码执行后,fruites一共包含了3个成员; fruites.length表示fruites的成员个数。
构造函数
Set 有如下工厂构造函数:
Set()创建一个空的SetSet.from(Iterable elements)从一个Iterable对象创建Set,可理解为将一个Iterable对象转换为SetSet.of(Iterable<E> elements)与Set.from类似,区别在于前者返回的是Set<E>对象,即带有类型参数ESet.identity()创建一个空的 identity Set,该Set使用identical(Object?, Object?)函数对成员进行相等性测试Set.unmodifiable(Iterable<E> elements)从elements创一个不可变Set
请阅读并分析下面的代码
// ex642.dart
import 'dart:math';
void main() {
var list = [1, 2, 2, 3];
var set1 = Set.from(list); // 1
print('${set1.runtimeType} $set1'); // Output: _Set<dynamic> {1, 2, 3}
var set2 = Set.of(list); // 2
print('${set2.runtimeType} $set2'); // Output: _Set<int> {1, 2, 3}
var a = Point(1, 2);
var b = Point(1, 2);
var set3 = Set.identity()
..add(a)
..add(b); // 3
print(set3); // Output: {Point(1, 2), Point(1, 2)}
var set4 = <dynamic>{}
..add(a)
..add(b); // 4
print(set4); // Output: {Point(1, 2)}
var set5 = Set.unmodifiable(set1);
set5.add(5);
// Unhandled exception:
// Unsupported operation: Cannot change an unmodifiable set
}
Set特色方法
与List一样,Set也实现了Iterable接口,即实现了Iterable接口定义的方法。由于在List章节中,我们已经对List的常用方法(包括Iterable接口中定义的方法)做了介绍,这里仅举例说明Set类型特有的方法。
// ex643.dart
void main() {
var set1 = {1, 2, 3};
var set2 = {2, 3, 4};
var set3 = set1.union(set2); // 1
print(set3); // Output: {1, 2, 3, 4}
var set4 = set1.intersection(set2); // 2
print(set4); // Output: {2, 3}
var set5 = set1.difference(set2); // 3
print(set5); // Output: {1}
var set6 = set2.difference(set1); // 3a
print(set6); // Output: {4}
var a = set1.lookup(1); // 4
print(a); // Output: 1
var b = set1.lookup(4); // 4a
print(b); // Output: null
}
union(Set<E> other)返回该Set与另一个Set(other)的并集;intersection(Set<Object?> other)返回该Set与另一个Set(other)的交集;difference(Set<Object?> other)返回该Set与另一个Set(other) 的差集,注意this.difference(other)与other.difference(this)是不同的;lookup(Object? object):如果Set中的某个成员与给定的对象object相等,就返回该成员,否则返回null。
关于Set的更多方法,请查阅官方文档。