Dart HashMap
last modified April 4, 2025
In Dart, HashMap is an unordered collection of key-value pairs. It provides fast lookup, addition, and deletion of entries based on keys.
HashMap implements the Map interface and uses hash tables for storage. Keys must
have consistent Object.== and Object.hashCode
implementations.
Creating a HashMap
The simplest way to create a HashMap is using the constructor.
import 'dart:collection';
void main() {
var capitals = HashMap<String, String>();
capitals['USA'] = 'Washington';
capitals['Japan'] = 'Tokyo';
capitals['France'] = 'Paris';
print(capitals);
}
We create a HashMap of country-capital pairs. The generic types specify that both keys and values are Strings. We add entries using the [] operator.
$ dart main.dart
{USA: Washington, France: Paris, Japan: Tokyo}
HashMap from Iterable
We can create a HashMap from an existing Iterable using HashMap.fromIterable.
import 'dart:collection';
void main() {
var fruits = ['apple', 'banana', 'orange'];
var fruitMap = HashMap.fromIterable(fruits,
key: (item) => item,
value: (item) => item.length);
print(fruitMap);
}
This creates a HashMap where fruits are keys and their lengths are values. The key and value parameters transform each element during creation.
$ dart main.dart
{orange: 6, banana: 6, apple: 5}
Checking Contents
HashMap provides methods to check for keys, values, and empty state.
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
}
We check various properties of the HashMap. Note that containsKey is O(1) while containsValue is O(n) in complexity.
$ dart main.dart true false false 3
Updating Values
HashMap provides several ways to update values, including update and 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);
}
The update method modifies existing entries, while putIfAbsent only adds if the key doesn't exist. Both methods help handle common update patterns safely.
$ dart main.dart
{oranges: 10, apples: 8}
Iterating Over HashMap
We can iterate through HashMap entries using various methods.
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'));
}
This demonstrates three ways to iterate through a HashMap. The order is undefined since HashMap doesn't guarantee insertion order.
$ dart main.dart Keys: red green blue Values: #FF0000 #00FF00 #0000FF Entries: red: #FF0000 green: #00FF00 blue: #0000FF
Removing Elements
HashMap provides methods to remove entries by key or clear the entire map.
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');
}
We demonstrate three removal methods. removeWhere is powerful for bulk removal based on conditions.
$ 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 with Custom Objects
When using custom objects as keys, we must implement hashCode and == properly.
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]}');
}
The Person class implements == and hashCode to ensure logical equality. p1 and p3 are considered the same key despite being different object instances.
$ dart main.dart
{Person(name: Bob, age: 25): Doctor, Person(name: Alice, age: 30): Manager}
p1 and p3 same key: true
Best Practices
- Key Immutability: Use immutable objects as keys for stability.
- Proper Hashing: Always override hashCode when overriding ==.
- Null Safety: Consider non-nullable types for clarity.
- Performance: Prefer containsKey over containsValue for O(1) checks.
Source
This tutorial covered Dart's HashMap with practical examples demonstrating its key features and usage patterns.
Author
List all Dart tutorials.