Dart - Copy/Clone Map (Shallow & Deep) Examples

This tutorial shows you how to copy or clone a Map in Dart and explains the difference between shallow copy and deep copy.

Dart supports Map data type. You can copy a Map into a new one using various methods. There are two kinds of copy, shallow copy and deep copy. Before you choose how to copy a Map, it's important to understand the difference between those two.

Shallow Copy/Clone

Shallow copy means the main object which is the Map is copied, but the inner objects (the elements) are not. An object can be mutable or immutable. If the element is immutable and you change the value, Dart will not be able to modify it and a new object with different memory location will be created. Therefore, using shallow copy should be safe if the element type of the Map is immutable, such as String, bool, int, or bool. Below are the examples of shallow copy using Dart's methods.

Using Map.of

The Map.of factory method can be used to copy a Map into a new one.

  factory Map.of(Map<K, V> other)

Example:

  var values = <int, String>{
    1: 'one',
    2: 'two',
    3: 'three',
  };
  var newValues = Map.of(values);

Using Map.from

This method is similar to Map.of, but you can use it to produce a new Map whose key and/or element type is a subtype of the source key and/or element type. It's used to create a new Map with more precise types. You have to make sure that all the keys and values have the more precise types.

  factory Map.from(Map other)

Example:

  var values = <num, String>{
    1: 'one',
    2: 'two',
    3: 'three',
  };
  Map<int, String> newValues = Map.from(values);

Using Map.unmodifiable

If you want to copy into a Map that cannot be modified, you can use Map.umodifiable factory method.

  factory Map.unmodifiable(Map<dynamic, dynamic> other)

Example:

  var types = Map.unmodifiable({
    1: 'one',
    2: 'two',
    3: 'three',
  });

Deep Copy/Clone

While shallow copy works for a Map with immutable elements, you may need to use deep copy for a Map with mutable elements. Using the examples above, if the element is mutable, Dart will only copy the reference to the object. The object itself is not copied. Therefore, if you modify an element of the source, it also affects the element of the new Map. If you don't want that behavior, you have to clone each element by creating a new object.

For example, we have a Map whose element type is Item. To create a new Item object from an existing one, we can create a factory method clone.

  class Item {
    String name;
  
    Item({
      required this.name,
    });
  
    factory Item.clone(Item source) {
      return Item(
        name: source.name,
      );
    }
  }

After that, use map method to map each element. You need to return a MapEntry and use the clone method above to copy the mutable object.

  var item1 = Item(name: 'One');
  var item2 = Item(name: 'Two');
  Map<int, Item> source = {1: item1, 2: item2};
  var clone = source.map((key, value) => MapEntry(key, Item.clone(value)));
  item1.name = 'Three';
  print(source[1]?.name); // Three
  print(clone[1]?.name); // One

Summary

That's how to copy a Map in Dart. If the Map only contains immutable key and element values, shallow copy should be enough. If either the key or value has mutable elements, you may have to perform deep copy.