Dart HashMap
最后修改于 2025 年 4 月 4 日
在 Dart 中,HashMap 是一个无序的键值对集合。它基于键提供了快速的查找、添加和删除条目。
HashMap 实现 Map 接口,并使用哈希表进行存储。键必须具有一致的 Object.== 和 Object.hashCode 实现。
创建 HashMap
创建 HashMap 的最简单方法是使用构造函数。
import 'dart:collection';
void main() {
var capitals = HashMap<String, String>();
capitals['USA'] = 'Washington';
capitals['Japan'] = 'Tokyo';
capitals['France'] = 'Paris';
print(capitals);
}
我们创建了一个国家-首都对的 HashMap。泛型类型指定键和值都是 String。我们使用 [] 运算符添加条目。
$ dart main.dart
{USA: Washington, France: Paris, Japan: Tokyo}
从 Iterable 创建 HashMap
我们可以使用 HashMap.fromIterable 从现有的 Iterable 创建 HashMap。
import 'dart:collection';
void main() {
var fruits = ['apple', 'banana', 'orange'];
var fruitMap = HashMap.fromIterable(fruits,
key: (item) => item,
value: (item) => item.length);
print(fruitMap);
}
这创建了一个以水果为键、其长度为值的 HashMap。key 和 value 参数在创建过程中转换每个元素。
$ dart main.dart
{orange: 6, banana: 6, apple: 5}
检查内容
HashMap 提供了检查键、值和空状态的方法。
import 'dart:collection';
void main() {
var scores = HashMap<String, int>();
scores['Alice'] = 90;
scores['Bob'] = 85;
scores['Charlie'] = 95;
print(scores.containsKey('Alice')); // true
print(scores.containsValue(100)); // false
print(scores.isEmpty); // false
print(scores.length); // 3
}
我们检查 HashMap 的各种属性。请注意,containsKey 的复杂度为 O(1),而 containsValue 的复杂度为 O(n)。
$ dart main.dart true false false 3
更新值
HashMap 提供了多种更新值的方法,包括 update 和 putIfAbsent。
import 'dart:collection';
void main() {
var inventory = HashMap<String, int>();
inventory['apples'] = 5;
// Update existing value
inventory.update('apples', (value) => value + 3);
// Add new value if absent
inventory.putIfAbsent('oranges', () => 10);
print(inventory);
}
update 方法修改现有条目,而 putIfAbsent 仅在键不存在时添加。这两种方法都有助于安全地处理常见的更新模式。
$ dart main.dart
{oranges: 10, apples: 8}
遍历 HashMap
我们可以使用各种方法遍历 HashMap 条目。
import 'dart:collection';
void main() {
var colors = HashMap<String, String>();
colors['red'] = '#FF0000';
colors['green'] = '#00FF00';
colors['blue'] = '#0000FF';
// Iterate keys
print('Keys:');
for (var key in colors.keys) {
print(key);
}
// Iterate values
print('\nValues:');
for (var value in colors.values) {
print(value);
}
// Iterate entries
print('\nEntries:');
colors.forEach((key, value) => print('$key: $value'));
}
这演示了遍历 HashMap 的三种方法。顺序是未定义的,因为 HashMap 不保证插入顺序。
$ dart main.dart Keys: red green blue Values: #FF0000 #00FF00 #0000FF Entries: red: #FF0000 green: #00FF00 blue: #0000FF
移除元素
HashMap 提供了按键删除条目或清除整个映射的方法。
import 'dart:collection';
void main() {
var users = HashMap<int, String>();
users[1] = 'Alice';
users[2] = 'Bob';
users[3] = 'Charlie';
users[4] = 'David';
print('Original: $users');
// Remove by key
users.remove(2);
print('After remove: $users');
// Remove where
users.removeWhere((key, value) => key.isEven);
print('After removeWhere: $users');
// Clear all
users.clear();
print('After clear: $users');
}
我们演示了三种删除方法。removeWhere 对于基于条件的大量删除非常有用。
$ dart main.dart
Original: {1: Alice, 2: Bob, 3: Charlie, 4: David}
After remove: {1: Alice, 3: Charlie, 4: David}
After removeWhere: {1: Alice, 3: Charlie}
After clear: {}
自定义对象的 HashMap
当使用自定义对象作为键时,我们必须正确实现 hashCode 和 ==。
import 'dart:collection';
class Person {
final String name;
final int age;
Person(this.name, this.age);
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Person && name == other.name && age == other.age;
@override
int get hashCode => name.hashCode ^ age.hashCode;
}
void main() {
var people = HashMap<Person, String>();
var p1 = Person('Alice', 30);
var p2 = Person('Bob', 25);
var p3 = Person('Alice', 30); // Same as p1
people[p1] = 'Engineer';
people[p2] = 'Doctor';
people[p3] = 'Manager';
print(people);
print('p1 and p3 same key: ${people[p1] == people[p3]}');
}
Person 类实现了 == 和 hashCode 以确保逻辑相等。尽管 p1 和 p3 是不同的对象实例,但它们被视为相同的键。
$ dart main.dart
{Person(name: Bob, age: 25): Doctor, Person(name: Alice, age: 30): Manager}
p1 and p3 same key: true
最佳实践
- 键的不可变性: 使用不可变对象作为键以获得稳定性。
- 正确的哈希: 重写 == 时,务必重写 hashCode。
- Null 安全: 考虑使用非可空类型以获得清晰性。
- 性能: 偏向于使用 containsKey 而不是 containsValue 以进行 O(1) 检查。
来源
本教程涵盖了 Dart 的 HashMap,并附有实际示例,展示了其关键功能和用法模式。
作者
列出 所有 Dart 教程。