Dart - Using Map, HashMap, LinkedHashMap, & SplayTreeMap Examples

Map in this context is a data structure consisting of key-value pairs. You can retrieve a value by providing its key. There are three Map implementations in Dart: HashMap, LinkedHashMap, and SplayTreeMap. They are different in terms of how the data is stored. However, the usage (constructors, methods and properties) are very similar. In this tutorial, I'm going to tell you the difference between those Map implementations, the basic usages as well as list of available constructors, methods and properties.

Map

Map is a collection of key/value pairs. In Dart, an entry of a Map is called MapEntry, which is a key/value pair. Retrieving a value can be done by using key name. Each entries in a Map can be iterated. The iteration order depends on the implementation HashMap, LinkedHashMap or SplayTreeMap. If you create an instance using Map constructor, it will create a LinkedHashMap by default.

HashMap

A HashMap doesn't guarantee insertion order. If you insert an entry with key A and then another entry with key B, when you iterate through the map, there's a possibility that you'll get entry B first.

LinkedHashMap

Data stored in a LinkedHashMap is sorted according to insertion order. If you insert an entry with key A and then another entry with key B, when you iterate through the map, you'll always get entry A first before entry B.

SplayTreeMap

A SplayTreeMap is a self-balancing binary tree that allows recently accessed elements to be accessed quicker. Basic operations like insertion, look-up and removal can be done in O(log(n)). It performs tree rotations by bringing frequently accessed elements close to the root of the tree. Therefore, if some entries need to be accessed more often than the others, using SplayTreeMap is a good choice. However, if the data access frequency is almost the same on all entries, using SplayTreeMap is useless.

Initialization

  import 'dart:collection';

  main() {
    HashMap map1 = new HashMap<int, String>();
    LinkedHashMap map2 = new LinkedHashMap<int, String>();
    SplayTreeMap map3 = new SplayTreeMap<int, String>();
  }

Add/Update Value

The simplest way to add or update the value of a key is by using square brackets. It will create a new MapEntry if no entry with the key found or update the value if there is an entry with the key.

  map1[1] = 'A';

To add a MapEntry only if an entry with the key doesn't exist in the map, use putIfAbsent method.

  map1.putIfAbsent(1, () => 'A');

To update a value if the key is already exist, use update method.

  hashMap.update(1, (e) => 'A');
  hashMap.update(1, (e) => '${e}A');

The first argument is the key, while the second argument is update function. The e parameter in the second argument function is the old value. So you can update the value based on old value, like incrementing the value if it is an integer or concatenating the old value to produce a new string like the second line of the above example. If you don't want to use the old value, just ignore it (without removing from the function argument)  like the first line of the above example.

The above code only works if the key is exist. Otherwise, you'll get error. To handle the case where the key is not exist, add the optional ifAbsent in the third argument, as exemplified below.

  hashMap.update(1, (e) => '${e}A', ifAbsent:  () => 'A');

Get Value by Key

To get a value if you know the key, access it by using square brackets.

  map1[1]

The code above is for getting the value of entry with key 1. If no entry with that key is found, it will return null.

Get Map Size

To get the number of entires of a map, use length property.

  map1.length

Check Key Existance

To check whether the map contains a certain key, use containsKey method.

  map1.containsKey(1)

Check Value Existance

Not only key, you can also check whether the map contains a certain value. To do so, use containsValue method.

  map1.containsValue('A')

Remove a Key

To remove a key from a map, you can use remove method.

  map1.remove(2);

Remove by Criteria

In case you want to remove entries from map with custom logic based on key and/or value, you can use removeWhere method. The code below is for removing entries whose key mod 2 equals 0 or whose value is C.

  hashMap.removeWhere((key, value) => key % 2 == 0 || value == 'C');

Clear All Entries

To clear all entries of a map, use clear method.

  map1.clear();

Iterate Through a Map

forEach method can be used for looping through each entry in a map.

  map1.forEach((key, value) {
    print('key: $key, value: $value');
  });

Map a Map

With map method, you can map not only the value of each entries, but also the key. For every entry, you need to return a new MapEntry.

  var mappedHashmap = map1.map((key, value) {
    return new MapEntry(key, '$value mapped');
  });
  print('mappedHashmap: $mappedHashmap');

Usage Examples

Below is the usage exaples of Map.

 import 'dart:collection';
  
  main() {
    HashMap map1 = new HashMap<int, String>();
    LinkedHashMap map2 = new LinkedHashMap<int, String>();
    SplayTreeMap map3 = new SplayTreeMap<int, String>();
  
    map1[1] = 'A';
    print('map1: $map1');
    // Print result:
    //    map1: {1: A}
  
    // This should be ignored because entry with key 1 is already exist.
    map1.putIfAbsent(1, () => 'A2');
  
    // This will add entry with key 2 and value B
    map1.putIfAbsent(2, () => 'B');
    print('map1: $map1');
    // Print result: xxx
    //    map1: {1: A, 2: B}
  
    print('map1.length: ${map1.length}');
    // Print result:
    //    map1.length: 2
  
    // This will update the value of entry with key 1 by appending 'A' character in the end
    map1.update(1, (e) => '${e}A', ifAbsent:  () => 'A');
  
    // This will create a new entry with key 3 and value C
    map1.update(3, (e) => '${e}C', ifAbsent:  () => 'C');
  
    print('map1: $map1');
    // Print result:
    //    map1: {1: AA, 2: B, 3: C}
  
    // Retrieve the value of entry with key 1
    print('Value of 1: ${map1[1]}');
    // Print result:
    //    Value of 1: AA
  
    // This will remove entry with key 2
    map1.remove(2);
    print('map1: $map1');
    // Print result:
    //    map1: {1: AA, 3: C}
  
    // This will remove entry whose key mods 2 equals 0 or whose value equals C
    map1.removeWhere((key, value) => key % 2 == 0 || value == 'C');
    print('map1: $map1');
    // Print result:
    //    map1: {1: AA}
  
    // Just adding other values
    map1[4] = 'D';
    map1[5] = 'E';
  
    // Iterate through map entries
    map1.forEach((key, value) {
      print('key: $key, value: $value');
    });
    // Print result:
    //    key: 1, value: AA
    //    key: 4, value: D
    //    key: 5, value: E
  
    var mappedHashMap = map1.map((key, value) {
      return new MapEntry(key, '$value mapped');
    });
    print('mappedHashMap: $mappedHashMap');
    // Print result:
    //    mappedHashMap: {1: AA mapped, 4: D mapped, 5: E mapped}
  
    map1.clear();
    print('map1: $map1');
    // Print result:
    //    map1: {}
  }

Below are the list of supported constructors, methods and properties of Map in Dart.

Constructors

Though the constructor list is for Map - HashMap and LinkedHashMap have similar constructors. Just replace the Map with HashMap or LinkedHashMap.

Name Parameters Description
Map ( {bool equals(K key1, K key2), int hashCode(K key), bool isValidKey(potentialKey)})

Creates a Map.

If equals is provided, it is used to compare the keys in the table with * new keys. If equals is omitted, the key's own Object.== is used * instead.

if ashCode is provided, it is used to produce a hash value * for keys in order to place them in the hash table. If it is omitted, the * key's own Object.hashCode is used.

Map.identity ( {bool equals(K key1, K key2), int hashCode(K key), bool isValidKey(potentialKey)}) Creates an identity-based map. Effectively a shorthand for: new HashMap<K, V>(equals: identical, hashCode: identityHashCode)
Map.from (Map other) Creates a Map that contains all key/value pairs of other.
Map.of (Map<K, V> other) Creates a Map that contains all key/value pairs of other.
Map.fromIterable ( {bool equals(K key1, K key2), int hashCode(K key), bool isValidKey(potentialKey)}) Creates a Map where the keys and values are computed from the iterable.
Map.fromIterables (Iterable keys, Iterable values) Creates a Map associating the given keys to values.
Map.fromEntries (Iterable<MapEntry<K, V>> entries) Creates a Map containing the entries of entries.

SplayTreeMap

SplayTreeMap has different constructors. It doesn't support identity and fromEntries, whereas the other constructors are available for it but with different parameters.

Name Parameters Description
SplayTreeMap ([int compare(K key1, K key2), bool isValidKey(potentialKey)])

Creates a SplayTreeMap.

SplayTreeMap.from (Map other, [int compare(K key1, K key2), bool isValidKey(potentialKey)]) Creates a SplayTreeMap that contains all key/value pairs of other.
SplayTreeMap.of (Map<K, V> other, [int compare(K key1, K key2), bool isValidKey(potentialKey)]) Creates a SplayTreeMap that contains all key/value pairs of other.
SplayTreeMap.fromIterable (Iterable iterable, {K key(element), V value(element), int compare(K key1, K key2), bool isValidKey(potentialKey)}) Creates a SplayTreeMap where the keys and values are computed from the iterable.
SplayTreeMap.fromIterables (Iterable keys, Iterable values, [int compare(K key1, K key2), bool isValidKey(potentialKey)]) { SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare, isValidKey); MapBase._fillMapWithIterables(map, keys, values) Creates a SplayTreeMap associating the given keys to values.

Methods

Name Parameters Description
Map<K2, V2> map<K2, V2> (MapEntry<K2, V2> f(K key, V value)); Returns a new map where all entries of this map are transformed by the given f function.
void addEntries (Iterable<MapEntry<K, V>> newEntries); Adds all key/value pairs of newEntries to this map.
Map<K2, V2> map<K2, V2> (MapEntry<K2, V2> f(K key, V value)); Returns a new map where all entries of this map are transformed by the given f function.
V update (K key, V update(V value), {V ifAbsent()}); Updates the value for the provided key. Returns the new value of the key.
void updateAll (V update(K key, V value)); Updates all values.
void removeWhere (bool predicate(K key, V value)); Removes all entries of this map that satisfy the given predicate.
V putIfAbsent (K key, V ifAbsent()); Look up the value of key, or add a new value if it isn't there.
void addAll (Map<K, V> other); Adds all key/value pairs of other to this map.
V remove (Object key); Removes key and its associated value, if present, from the map.
void clear (); Removes all pairs from the map.
void forEach (void f(K key, V value)); Applies f to each key/value pair of the map.

Properties

Property Type Description
keys Iterable Gets the list of keys
values Iterable Gets the list of values
length Iterable The number of key/value pairs in the map.
isEmpty bool Returns true if there is no key/value pair in the map.
isNotEmpty bool Returns true if there is at least one key/value pair in the map.
entries Iterable<MapEntry<K, V>> The map entries of this.
hashCode int The hash code for this object.