ZetCode

Dart Set

最后修改于 2025 年 4 月 4 日

在 Dart 中,Set 是一个包含唯一元素的集合。它不允许重复值,并提供高效的成员资格测试操作。

Set 实现了 Iterable 接口,并提供了像 union(并集)、intersection(交集)和 difference(差集)这样的数学集合操作方法。元素必须具有一致的 Object.==Object.hashCode 实现。

创建集合

创建 Set 最简单的方法是使用 Set 构造函数或字面量语法。

main.dart
void main() {
  // Using constructor
  var numbers = Set<int>();
  numbers.add(1);
  numbers.add(2);
  numbers.add(3);
  
  // Using literal
  var colors = {'red', 'green', 'blue'};
  
  print(numbers);
  print(colors);
}

我们创建了两个 Set:一个使用构造函数,另一个使用字面量语法。泛型类型指定了元素的类型。重复项会被自动删除。

$ dart main.dart
{1, 2, 3}
{red, green, blue}

基本 Set 操作

Set 提供了添加、删除和检查元素的方法。

main.dart
void main() {
  var fruits = {'apple', 'banana', 'orange'};
  
  // Add elements
  fruits.add('pear');
  fruits.addAll(['kiwi', 'mango']);
  
  // Check elements
  print(fruits.contains('apple')); // true
  print(fruits.contains('grape')); // false
  
  // Remove elements
  fruits.remove('banana');
  fruits.removeWhere((fruit) => fruit.startsWith('m'));
  
  print(fruits);
}

我们演示了基本的 Set 操作。addAll 用于添加多个元素,而 removeWhere 用于删除满足条件的元素。contains 用于检查成员资格。

$ dart main.dart
true
false
{apple, orange, pear, kiwi}

集合操作

Set 支持并集、交集和差集等数学运算。

main.dart
void main() {
  var set1 = {1, 2, 3, 4, 5};
  var set2 = {4, 5, 6, 7, 8};
  
  // Union
  print(set1.union(set2));
  
  // Intersection
  print(set1.intersection(set2));
  
  // Difference
  print(set1.difference(set2));
  
  // Check subset
  print(set1.containsAll({2, 3})); // true
}

这些操作会创建新的 Set,而不会修改原始 Set。union 用于合并元素,intersection 用于查找共同元素,difference 用于查找 set1 中不包含在 set2 中的元素。

$ dart main.dart
{1, 2, 3, 4, 5, 6, 7, 8}
{4, 5}
{1, 2, 3}
true

遍历 Set

由于 Set 实现了 Iterable,因此可以使用多种方法进行遍历。

main.dart
void main() {
  var languages = {'Dart', 'Python', 'Java', 'Go', 'Rust'};
  
  // for-in loop
  for (var lang in languages) {
    print(lang);
  }
  
  // forEach method
  languages.forEach((lang) => print(lang.toUpperCase()));
  
  // map and where
  var shortNames = languages.where((lang) => lang.length <= 4);
  print(shortNames);
}

我们演示了三种处理 Set 元素的方法。遍历顺序是不指定的,但在单个程序运行中是一致的。

$ dart main.dart
Dart
Python
Java
Go
Rust
DART
PYTHON
JAVA
GO
RUST
{Dart, Java, Go}

包含自定义对象的 Set

在 Set 中使用自定义对象时,需要正确实现 == 和 hashCode。

main.dart
class Book {
  final String title;
  final String author;
  
  Book(this.title, this.author);
  
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Book && title == other.title && author == other.author;
  
  @override
  int get hashCode => title.hashCode ^ author.hashCode;
}

void main() {
  var library = Set<Book>();
  var book1 = Book('Dart in Action', 'Manning');
  var book2 = Book('Flutter Cookbook', 'Packt');
  var book3 = Book('Dart in Action', 'Manning'); // Same as book1
  
  library.add(book1);
  library.add(book2);
  library.add(book3);
  
  print(library);
  print('book1 and book3 same: ${library.contains(book3)}');
}

Book 类实现了 == 和 hashCode 来确保逻辑相等性。尽管 book1 和 book3 是不同的实例,但它们被认为是相等的,因此只有一个会被添加到 Set 中。

$ dart main.dart
{Book(Dart in Action, Manning), Book(Flutter Cookbook, Packt)}
book1 and book3 same: true

最佳实践

来源

Dart Set 文档

本教程介绍了 Dart 的 Set 接口,并通过实际示例演示了其用于唯一元素集合的关键特性和使用模式。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 Dart 教程