Dart MapView
最后修改于 2025 年 4 月 4 日
在 Dart 中,MapView 是 Map 的一个不可修改的视图。它提供对底层 map 数据的只读访问,同时阻止修改。
MapView 实现 Map 接口,但对于会修改 map 的操作会抛出 UnsupportedError。它对于安全地暴露 map 数据很有用。
创建 MapView
创建 MapView 最简单的方法是使用 MapView.of 构造函数。
main.dart
import 'dart:collection';
void main() {
var originalMap = {'a': 1, 'b': 2, 'c': 3};
var view = MapView.of(originalMap);
print(view);
print(view['b']); // Access works
try {
view['d'] = 4; // Will throw
} catch (e) {
print(e); // UnsupportedError
}
}
我们从一个现有的 map 创建一个 MapView。虽然我们可以读取值,但任何尝试修改视图的操作都会抛出 UnsupportedError。
$ dart main.dart
{a: 1, b: 2, c: 3}
2
UnsupportedError: Cannot modify unmodifiable map
带不同 Map 类型的 MapView
MapView 可以与任何 Map 实现一起工作,包括 HashMap 和 LinkedHashMap。
main.dart
import 'dart:collection';
void main() {
var hashMap = HashMap<String, int>();
hashMap.addAll({'x': 10, 'y': 20, 'z': 30});
var linkedMap = LinkedHashMap<String, int>();
linkedMap.addAll({'first': 1, 'second': 2});
var hashView = MapView.of(hashMap);
var linkedView = MapView.of(linkedMap);
print('HashMap view: $hashView');
print('LinkedHashMap view: $linkedView');
}
这表明 MapView 在不同的 Map 实现中一致工作。该视图保留了原始 map 的特性。
$ dart main.dart
HashMap view: {x: 10, z: 30, y: 20}
LinkedHashMap view: {first: 1, second: 2}
MapView 操作
MapView 支持 Map 接口的所有读取操作。
main.dart
import 'dart:collection';
void main() {
var scores = {'Alice': 90, 'Bob': 85, 'Charlie': 95};
var scoreView = MapView.of(scores);
print('Keys: ${scoreView.keys}');
print('Values: ${scoreView.values}');
print('Length: ${scoreView.length}');
print('Contains Alice: ${scoreView.containsKey('Alice')}');
print('Alice\'s score: ${scoreView['Alice']}');
scoreView.forEach((k, v) => print('$k: $v'));
}
所有不修改的 Map 操作在 MapView 上都能正常工作。该视图反映了对原始 map 所做的更改。
$ dart main.dart Keys: (Alice, Bob, Charlie) Values: (90, 85, 95) Length: 3 Contains Alice: true Alice's score: 90 Alice: 90 Bob: 85 Charlie: 95
原始 Map 的实时视图
MapView 提供了一个实时视图,可以反映对原始 map 的更改。
main.dart
import 'dart:collection';
void main() {
var original = {'a': 1, 'b': 2};
var view = MapView.of(original);
print('Initial view: $view');
original['c'] = 3;
print('After original modification: $view');
original.remove('a');
print('After original removal: $view');
}
对原始 map 的更改会立即在 MapView 中可见。这使得 MapView 非常适合需要安全共享数据的场景。
$ dart main.dart
Initial view: {a: 1, b: 2}
After original modification: {a: 1, b: 2, c: 3}
After original removal: {b: 2, c: 3}
将 MapView 与其他集合结合使用
MapView 可以与其他不可修改的集合结合使用,以实现完全安全。
main.dart
import 'dart:collection';
void main() {
var data = {
'users': ['Alice', 'Bob'],
'scores': [90, 85],
'active': true
};
var unmodifiableMap = UnmodifiableMapView(data);
var unmodifiableLists = unmodifiableMap.map(
(key, value) => MapEntry(
key,
value is List ? List.unmodifiable(value) : value
)
);
print(unmodifiableLists);
try {
unmodifiableLists['users'].add('Charlie'); // Fails
} catch (e) {
print(e); // UnsupportedError
}
}
我们通过将 MapView 与不可修改的列表结合来创建一个完全不可修改的结构。这可以在所有级别上阻止修改。
$ dart main.dart
{users: [Alice, Bob], scores: [90, 85], active: true}
UnsupportedError: Cannot add to an unmodifiable list
最佳实践
- 数据安全: 当你需要共享 map 数据而不允许修改时,请使用 MapView。
- 性能: MapView 的开销很小,因为它不复制数据。
- 不可变性: 与其他不可修改的集合结合使用,以实现完全不可变。
- 文档: 清晰记录 API 何时返回 MapView,以设定适当的期望。
来源
本教程通过实际示例介绍了 Dart 的 MapView,演示了其创建不可修改 map 视图的关键功能和用法模式。
作者
列出 所有 Dart 教程。