Dart UnmodifiableSetView
最后修改于 2025 年 4 月 4 日
在 Dart 中,UnmodifiableSetView 是 Set 的一个不可修改视图,可以防止对底层集合的修改。它封装了一个现有的 Set。
UnmodifiableSetView 实现 Set 接口,但会为修改操作抛出异常。它有助于为 Set 提供只读访问。
创建 UnmodifiableSetView
创建 UnmodifiableSetView 的最简单方法是使用构造函数。
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。
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 接口的所有读取操作。
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 迭代方法。
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(交集)。
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
最佳实践
- 不可修改 API:对于不应被修改的公共 API,请使用 UnmodifiableSetView。
- 性能:对于大型 Set,优先使用 UnmodifiableSetView 而不是复制。
- 防御性编程:在将 Set 传递给不受信任的代码时,请将其封装在视图中。
- 文档:清楚地记录 API 返回不可修改视图的情况。
来源
本教程介绍了 Dart 的 UnmodifiableSetView,并通过实际示例演示了其功能和用于不可修改 Set 操作的使用模式。
作者
列出 所有 Dart 教程。