ZetCode

Dart UnmodifiableMapView

最后修改于 2025 年 4 月 4 日

在 Dart 中,UnmodifiableMapView 是 Map 的一个不可修改视图。它在阻止修改的同时,提供了对现有 Map 的只读访问。

UnmodifiableMapView 实现了 Map 接口,但对修改操作会抛出异常。它对于安全地暴露内部 Map 非常有用。

创建 UnmodifiableMapView

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

main.dart
import 'dart:collection';

void main() {
  
  var originalMap = {'a': 1, 'b': 2, 'c': 3};
  var unmodifiableView = UnmodifiableMapView(originalMap);

  print(unmodifiableView);
  
  try {
    unmodifiableView['d'] = 4; // Throws
  } catch (e) {
    print('Error: $e');
  }
}

我们创建了一个普通 Map 的不可修改视图。尝试修改它会抛出 UnsupportedError。视图会反映原始 Map 的更改。

$ dart main.dart
{a: 1, b: 2, c: 3}
Error: Unsupported operation: Cannot modify unmodifiable map

带 Map 方法的 UnmodifiableMapView

UnmodifiableMapView 支持 Map 接口的所有读取操作。

main.dart
import 'dart:collection';

void main() {
  
  var scores = {'Alice': 95, 'Bob': 87, 'Charlie': 92};
  var view = UnmodifiableMapView(scores);

  print('Alice\'s score: ${view['Alice']}');
  print('Contains Bob? ${view.containsKey('Bob')}');
  print('Keys: ${view.keys}');
  print('Values: ${view.values}');
  print('Length: ${view.length}');
}

我们演示了 UnmodifiableMapView 的各种读取操作。所有这些操作与普通 Map 的工作方式相同,但可以防止修改。

$ dart main.dart
Alice's score: 95
Contains Bob? true
Keys: (Alice, Bob, Charlie)
Values: (95, 87, 92)
Length: 3

来自原始 Map 的动态更新

UnmodifiableMapView 会反映对原始底层 Map 所做的更改。

main.dart
import 'dart:collection';

void main() {
  
  var original = {'x': 10, 'y': 20};
  var view = UnmodifiableMapView(original);

  print('Initial view: $view');
  
  original['z'] = 30;
  print('After original modification: $view');
  
  original.remove('x');
  print('After original removal: $view');
}

对原始 Map 的更改会立即在视图中可见。视图本身保持不可修改,而原始 Map 仍然可以更改。

$ dart main.dart
Initial view: {x: 10, y: 20}
After original modification: {x: 10, y: 20, z: 30}
After original removal: {y: 20, z: 30}

迭代 UnmodifiableMapView

UnmodifiableMapView 支持所有标准的 Map 迭代方法。

main.dart
import 'dart:collection';

void main() {
  
  var colors = {'red': '#FF0000', 'green': '#00FF00', 'blue': '#0000FF'};
  var unmodifiableColors = UnmodifiableMapView(colors);

  print('Keys:');
  for (var key in unmodifiableColors.keys) {
    print(key);
  }

  print('\nValues:');
  for (var value in unmodifiableColors.values) {
    print(value);
  }

  print('\nEntries:');
  unmodifiableColors.forEach((key, value) => print('$key: $value'));
}

我们演示了三种迭代 UnmodifiableMapView 的方法。视图保持与原始 Map 相同的迭代顺序。

$ dart main.dart
Keys:
red
green
blue

Values:
#FF0000
#00FF00
#0000FF

Entries:
red: #FF0000
green: #00FF00
blue: #0000FF

带自定义对象的 UnmodifiableMapView

UnmodifiableMapView 与自定义对象一样,可以像普通 Map 一样工作。

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 = {
    Product('p1', 'Laptop'): 999,
    Product('p2', 'Phone'): 699,
  };
  
  var unmodifiableProducts = UnmodifiableMapView(products);
  
  var searchKey = Product('p1', 'Laptop');
  print('Laptop price: \$${unmodifiableProducts[searchKey]}');
  
  try {
    unmodifiableProducts[Product('p3', 'Tablet')] = 299;
  } catch (e) {
    print('Error: $e');
  }
}

我们将自定义 Product 对象用作 UnmodifiableMapView 中的键。视图在防止修改的同时正确处理键查找。

$ dart main.dart
Laptop price: $999
Error: Unsupported operation: Cannot modify unmodifiable map

最佳实践

来源

Dart UnmodifiableMapView 文档

本教程通过实际示例涵盖了 Dart 的 UnmodifiableMapView,演示了其关键特性和用法模式。

作者

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

列出 所有 Dart 教程