ZetCode

Dart UnmodifiableSetView

最后修改于 2025 年 4 月 4 日

在 Dart 中,UnmodifiableSetView 是 Set 的一个不可修改视图,可以防止对底层集合的修改。它封装了一个现有的 Set。

UnmodifiableSetView 实现 Set 接口,但会为修改操作抛出异常。它有助于为 Set 提供只读访问。

创建 UnmodifiableSetView

创建 UnmodifiableSetView 的最简单方法是使用构造函数。

main.dart
import 'dart:collection';

void main() {
  var numbers = {1, 2, 3};
  var unmodifiableView = UnmodifiableSetView(numbers);
  
  print(unmodifiableView);
  
  try {
    unmodifiableView.add(4); // Will throw
  } catch (e) {
    print('Error: $e');
  }
}

我们从一个常规 Set 创建一个 UnmodifiableSetView。尝试修改它会抛出 UnsupportedError。该视图会反映原始 Set 的更改。

$ dart main.dart
{1, 2, 3}
Error: Unsupported operation: Cannot modify an unmodifiable set

来自 Set.unmodifiable 的 UnmodifiableSetView

Dart 的 Set.unmodifiable 工厂会在内部创建一个 UnmodifiableSetView。

main.dart
import 'dart:collection';

void main() {
  var colors = {'red', 'green', 'blue'};
  var unmodifiableColors = Set.unmodifiable(colors);
  
  print(unmodifiableColors.runtimeType);
  print(unmodifiableColors);
  
  // Changes to original don't affect the unmodifiable copy
  colors.add('yellow');
  print(unmodifiableColors);
}

Set.unmodifiable 会创建原始 Set 的快照。与 UnmodifiableSetView 不同,对原始 Set 的更改不会影响该副本。

$ dart main.dart
UnmodifiableSetView<String>
{red, green, blue}
{red, green, blue}

检查内容

UnmodifiableSetView 支持 Set 接口的所有读取操作。

main.dart
import 'dart:collection';

void main() {
  var fruits = {'apple', 'banana', 'orange'};
  var view = UnmodifiableSetView(fruits);
  
  print('Contains apple: ${view.contains('apple')}');
  print('Length: ${view.length}');
  print('First element: ${view.first}');
  print('Last element: ${view.last}');
  print('Is empty: ${view.isEmpty}');
}

我们演示了 UnmodifiableSetView 上可用的各种读取操作。这些操作与常规 Set 的操作相同,但保证是安全的。

$ dart main.dart
Contains apple: true
Length: 3
First element: apple
Last element: orange
Is empty: false

迭代 UnmodifiableSetView

UnmodifiableSetView 支持所有标准的 Set 迭代方法。

main.dart
import 'dart:collection';

void main() {
  var primes = {2, 3, 5, 7, 11};
  var primeView = UnmodifiableSetView(primes);
  
  print('Using for-in:');
  for (var prime in primeView) {
    print(prime);
  }
  
  print('\nUsing forEach:');
  primeView.forEach(print);
  
  print('\nUsing where:');
  var largePrimes = primeView.where((p) => p > 5);
  print(largePrimes);
}

我们演示了三种迭代 UnmodifiableSetView 的方法。该视图提供了与常规 Set 相同的迭代功能,但它是不可修改的。

$ dart main.dart
Using for-in:
2
3
5
7
11

Using forEach:
2
3
5
7
11

Using where:
(7, 11)

集合操作

UnmodifiableSetView 支持非修改性的 Set 操作,如 union(联合)和 intersection(交集)。

main.dart
import 'dart:collection';

void main() {
  var setA = UnmodifiableSetView({1, 2, 3, 4});
  var setB = UnmodifiableSetView({3, 4, 5, 6});
  
  print('Union: ${setA.union(setB)}');
  print('Intersection: ${setA.intersection(setB)}');
  print('Difference: ${setA.difference(setB)}');
  
  print('\nLookups:');
  print('Contains 3: ${setA.contains(3)}');
  print('Lookup 5: ${setA.lookup(5)}');
}

这些操作会返回新的 Set,而不是修改现有的视图。原始 UnmodifiableSetView 在这些操作后保持不变。

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

Lookups:
Contains 3: true
Lookup 5: null

最佳实践

来源

Dart UnmodifiableSetView 文档

本教程介绍了 Dart 的 UnmodifiableSetView,并通过实际示例演示了其功能和用于不可修改 Set 操作的使用模式。

作者

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

列出 所有 Dart 教程