ZetCode

Dart HashMap

最后修改于 2025 年 4 月 4 日

在 Dart 中,HashMap 是一个无序的键值对集合。它基于键提供了快速的查找、添加和删除条目。

HashMap 实现 Map 接口,并使用哈希表进行存储。键必须具有一致的 Object.==Object.hashCode 实现。

创建 HashMap

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

main.dart
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。

main.dart
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 提供了检查键、值和空状态的方法。

main.dart
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。

main.dart
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 条目。

main.dart
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 提供了按键删除条目或清除整个映射的方法。

main.dart
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 和 ==。

main.dart
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

最佳实践

来源

Dart HashMap 文档

本教程涵盖了 Dart 的 HashMap,并附有实际示例,展示了其关键功能和用法模式。

作者

我叫 Jan Bodnar,是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写超过 1,400 篇文章和 8 本电子书。我在教学编程方面拥有十多年的经验。

列出 所有 Dart 教程