ZetCode

Dart SetBase

最后修改于 2025 年 4 月 4 日

在 Dart 中,SetBase 是一个抽象的基类,用于集合集,它包含了所有集合集实现体的通用功能。它提供了处理唯一元素集合的操作。

SetBase 实现核心的 Set 接口,并为许多方法提供了默认实现。集合集中的所有元素都必须是唯一的,并且必须具有一致的 Object.== 实现。

使用 SetBase 创建集合集

虽然 SetBase 是抽象的,但我们可以使用它的具体实现,如 HashSet,来演示其功能。

main.dart
import 'dart:collection';

void main() {
  var numbers = HashSet<int>();
  numbers.add(1);
  numbers.add(2);
  numbers.add(3);
  numbers.add(2); // Duplicate, won't be added

  print(numbers);
}

我们创建了一个扩展 SetBase 的 HashSet。我们使用 add() 添加元素,重复的元素会自动被忽略。泛型指定了我们存储的是整数。

$ dart main.dart
{1, 2, 3}

集合操作

SetBase 提供了标准的集合集操作,如联合、交集和差集。

main.dart
import 'dart:collection';

void main() {
  var set1 = HashSet<int>.from([1, 2, 3, 4]);
  var set2 = HashSet<int>.from([3, 4, 5, 6]);

  print('Union: ${set1.union(set2)}');
  print('Intersection: ${set1.intersection(set2)}');
  print('Difference: ${set1.difference(set2)}');
}

我们演示了三种基本的集合集操作。联合合并两个集合集中的元素,交集查找共同的元素,差集显示 set1 中不包含在 set2 中的元素。

$ dart main.dart
Union: {1, 2, 3, 4, 5, 6}
Intersection: {3, 4}
Difference: {1, 2}

检查集合集内容

SetBase 提供了检查元素存在性和集合集关系的方法。

main.dart
import 'dart:collection';

void main() {
  var fruits = HashSet<String>.from(['apple', 'banana', 'orange']);

  print(fruits.contains('apple')); // true
  print(fruits.contains('grape')); // false
  print(fruits.containsAll(['apple', 'banana'])); // true
  print(fruits.isEmpty); // false
  print(fruits.length); // 3
}

我们检查集合集的各种属性。contains() 检查单个元素,而 containsAll() 验证多个元素。isEmpty 和 length 提供大小信息。

$ dart main.dart
true
false
true
false
3

修改集合集

SetBase 提供了修改集合集的方法,包括添加和删除元素。

main.dart
import 'dart:collection';

void main() {
  var colors = HashSet<String>.from(['red', 'green', 'blue']);

  // Add elements
  colors.add('yellow');
  colors.addAll(['purple', 'cyan']);

  // Remove elements
  colors.remove('green');
  colors.removeWhere((color) => color.startsWith('b'));

  print(colors);
}

我们使用 add() 演示添加单个元素,使用 addAll() 演示添加多个元素。我们使用 remove() 删除元素,并使用 removeWhere() 有条件地删除元素。

$ dart main.dart
{red, yellow, purple, cyan}

遍历集合集

SetBase 提供了多种遍历集合集元素的方式。

main.dart
import 'dart:collection';

void main() {
  var primes = HashSet<int>.from([2, 3, 5, 7, 11]);

  // Using for-in loop
  print('For-in loop:');
  for (var prime in primes) {
    print(prime);
  }

  // Using forEach
  print('\nForEach:');
  primes.forEach((prime) => print(prime));

  // Using iterator
  print('\nIterator:');
  var it = primes.iterator;
  while (it.moveNext()) {
    print(it.current);
  }
}

我们演示了三种遍历方法。由于 HashSet 不保证元素的顺序,因此顺序是未定义的。所有方法都提供对集合集中每个元素的访问。

$ dart main.dart
For-in loop:
2
3
5
7
11

ForEach:
2
3
5
7
11

Iterator:
2
3
5
7
11

SetBase 与自定义对象

在集合集中使用自定义对象时,正确的 hashCode 和 == 实现至关重要。

main.dart
import 'dart:collection';

class Product {
  final String id;
  final String name;

  Product(this.id, this.name);

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Product && id == other.id && name == other.name;

  @override
  int get hashCode => id.hashCode ^ name.hashCode;
}

void main() {
  var products = HashSet<Product>();
  var p1 = Product('1', 'Laptop');
  var p2 = Product('2', 'Phone');
  var p3 = Product('1', 'Laptop'); // Same as p1

  products.add(p1);
  products.add(p2);
  products.add(p3);

  print('Set size: ${products.length}');
  print('Contains p1: ${products.contains(p1)}');
  print('Contains p3: ${products.contains(p3)}');
}

Product 类实现了 == 和 hashCode 以确保逻辑相等性。p1 和 p3 被认为是相等的,因此 p3 不会被添加到集合集中。这保持了集合集的唯一性保证。

$ dart main.dart
Set size: 2
Contains p1: true
Contains p3: true

最佳实践

来源

Dart SetBase 文档

本教程通过实际示例介绍了 Dart 的 SetBase,演示了其处理唯一元素集合的关键特性和用法模式。

作者

我叫 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。自 2007 年以来我一直在撰写编程文章。到目前为止,我已撰写了 1400 多篇文章和 8 本电子书。我在教授编程方面拥有十多年的经验。

列出 所有 Dart 教程