devstory

Le Tutoriel de Dart Map

  1. Map<K,V>
  2. Constructors
  3. Properties
  4. Methods
  5. addAll(Map<K, V> other)
  6. addEntries(..)
  7. cast<RK, RV>()
  8. castFrom<K, V, K2, V2>(..)
  9. clear()
  10. containsKey(Object? key)
  11. containsValue(Object? value)
  12. forEach(..)
  13. putIfAbsent(..)
  14. remove(Object? key)
  15. removeWhere(..)
  16. update(..)
  17. updateAll(..)

1. Map<K,V>

Dans le langage Dart, la classe Map<K,V> représente une structure de données constituée de mappages entre les clefs et les valeurs. Les clefs ne peuvent pas être dupliquées et chaque clef correspondra à une valeur.
L'un des exemples typiques que l'on peut mentionner est un annuaire téléphonique. Le numéro de téléphone est la clef et le nom du propriétaire du numéro de téléphone est une valeur.
map_ex1.dart
void main() {
  Map<String, String> phonebook =  {
    '01000005': 'Tom',
    '01000002': 'Jerry',
    '01000003': 'Tom',
    '01000004': 'Donald'
  };
  Iterable<String> phoneNumbers = phonebook.keys;

  for (var phoneNumber in phoneNumbers) {
    String? name = phonebook[phoneNumber];
    print('Phone Number: $phoneNumber ==> Name: $name');
  }
  print(' ------------- ');
  var phoneNumber = '99999999';
  String? name = phonebook[phoneNumber];
  print('Phone Number: $phoneNumber ==> Name: $name');
}
Output:
Phone Number: 01000005 ==> Name: Tom
Phone Number: 01000002 ==> Name: Jerry
Phone Number: 01000003 ==> Name: Tom
Phone Number: 01000004 ==> Name: Donald
 -------------
Phone Number: 99999999 ==> Name: null
La hiérarchie des classes du groupe Map:
  • LinkedHashMap

2. Constructors

Les constructeurs :
external factory Map();
factory Map.from(Map other) = LinkedHashMap<K, V>.from;
factory Map.of(Map<K, V> other) = LinkedHashMap<K, V>.of;
external factory Map.unmodifiable(Map<dynamic, dynamic> other);
factory Map.identity() = LinkedHashMap<K, V>.identity;  

factory Map.fromIterable(Iterable iterable,
             {K key(dynamic element)?, V value(dynamic element)?}) = LinkedHashMap<K, V>.fromIterable;  
    
factory Map.fromIterables(Iterable<K> keys, Iterable<V> values) = LinkedHashMap<K, V>.fromIterables;
factory Map.fromEntries(Iterable<MapEntry<K, V>> entries) =>  <K, V>{}..addEntries(entries);
Map()
external factory Map();
Créer une LinkedHashMap vide.
Map.from(Map other)
factory Map.from(Map other) = LinkedHashMap<K, V>.from;
Créer une LinkedHashMap avec tous les mappages importés depuis other.
Ce constructeur ne vérifie pas le type de données de other, donc une erreur peut se produire lors de l'exécution de l'application. Vous devriez préférer utiliser le constructeur Map.of si possible.
Par exemple :
map_from_ex1.dart
void main()  {
  Map<String, dynamic> other = {
    'A' : 'A1',
    'B' : 'B1',
    'C' : 100  // ---> int type !!!!!!!
  };
  Map<String,String> map = Map.from(other); // Compile OK, but throw Error at runtime!
  print(map); 
}
Output:
Unhandled exception:
type 'int' is not a subtype of type 'String' in type cast
#0      new LinkedHashMap.from.<anonymous closure> (dart:collection/linked_hash_map.dart:88:26)
#1      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:397:8)
#2      new LinkedHashMap.from (dart:collection/linked_hash_map.dart:87:11)
#3      main
bin/map_from_ex1.dart:7
#4      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:283:19)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
Map.of(Map<K, V> other)
factory Map.of(Map<K, V> other) = LinkedHashMap<K, V>.of;
Créer un LinkedHashMap avec tous les mappages importés depuis other.
Map.identity()
factory Map.identity() = LinkedHashMap<K, V>.identity;
Renvoyer une "Identity Map", qui est une Map qui utilise un hashcode et la fonction identical pour comparer deux clefs. (Voir plus d'explications dans l'article sur LinkedHashMap).
  • Dart LinkedHashMap
Map.unmodifiable(..)
external factory Map.unmodifiable(Map<dynamic, dynamic> other);
Créer un objet Map non modifiable, avec tous les mappages importés depuis other.
Map.fromIterable(..)
factory Map.fromIterable(Iterable iterable,
             {K key(dynamic element)?, V value(dynamic element)?}) = LinkedHashMap<K, V>.fromIterable;
Créer un objet Map avec des clefs et des valeurs calculées à partir des éléments d'un Iterable spécifié.
map_fromIterable_ex1.dart
void main()  {
  var iterable = [1, 2, 3, 4, 5];

  var map = Map<int,int>.fromIterable(iterable,
      key : (element)  {
        return element;
      } // Optional Named Parameter.
      ,
      value : (element)  {
         return element * element;
      } // Optional Named Parameter.
  );
  print(map); // {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
}
Map.fromEntries(..)
factory Map.fromEntries(Iterable<MapEntry<K, V>> entries) =>  <K, V>{}..addEntries(entries);
Créer une Mao avec les mappages obtenus à partir du MapEntry fourni.
map_fromEntries_ex1.dart
void main() {
  MapEntry<String, String> entry1 = MapEntry('01000005', 'Tom');
  var entry2 = MapEntry('01000002', 'Jerry');
  var entry3 = MapEntry('01000004', 'Donald');

  // Create an Iterable via the List syntax.
  Iterable<MapEntry<String, String>> entries = [entry1, entry2, entry3];
  var phonebook = Map.fromEntries(entries);

  print(phonebook); // {01000005: Tom, 01000002: Jerry, 01000004: Donald}
}

3. Properties

Les propriétés :
Iterable<K> get keys;
Iterable<V> get values;
Iterable<MapEntry<K, V>> get entries;
int get length;
bool get isEmpty;
bool get isNotEmpty;

4. Methods

Les méthodes :
// Operators:
V? operator [](Object? key);

// Methods:
static Map<K2, V2> castFrom<K, V, K2, V2>(Map<K, V> source) => CastMap<K, V, K2, V2>(source);  
    
Map<RK, RV> cast<RK, RV>();
bool containsValue(Object? value);
bool containsKey(Object? key);

void addEntries(Iterable<MapEntry<K, V>> newEntries);
V update(K key, V update(V value), {V ifAbsent()?});
void updateAll(V update(K key, V value));
void removeWhere(bool test(K key, V value));
V putIfAbsent(K key, V ifAbsent());
void addAll(Map<K, V> other);
V? remove(Object? key);
void clear();
void forEach(void action(K key, V value));

5. addAll(Map<K, V> other)

void addAll(Map<K, V> other);
Ajouter toutes les paires clef et valeur de other à cette Map. Si la clef existe déjà dans Map, sa valeur correspondante sera remplacée par la nouvelle valeur.
map_addAll_ex1.dart
void main() {
  // Map<String,String>
  var options = {
    'configFile': 'config.conf',
    'outDir': './work/out',
    'inputDir': './work/in'
  };
  // Map<String,String>
  var other = {
    'outDir': './data/output',
    'inputDir': './data/input',
    'libraryDir': './libs',
    'logDir': './logs'
  };
  options.addAll(other);
  for (var entry in options.entries) {
    print('${entry.key} --> ${entry.value}');
  }
}
Output:
configFile --> config.conf
outDir --> ./data/output
inputDir --> ./data/input
libraryDir --> ./libs
logDir --> ./logs

6. addEntries(..)

void addEntries(Iterable<MapEntry<K, V>> newEntries);
Ajouter toutes les paires clé et valeur de MapEntry(s) à cette Map. Si la clef existe déjà, sa valeur correspondante sera remplacée par la nouvelle valeur.
Par exemple :
map_addEntries_ex1.dart
void main() {
  // Employee Number --> Salary
  // Map<String,int>
  var empSalaryMap =  {
    'E01': 800,
    'E02': 20000,
    'E03': 700
  };
  MapEntry<String,int> entry3 = MapEntry('E03', 3000);
  var entry4 = MapEntry('E04', 4000);
  var entry5 = MapEntry('E05', 5000);

  // Create an Iterable through the List syntax.
  Iterable<MapEntry<String,int>> newEntries = [entry3, entry4, entry5];
  empSalaryMap.addEntries(newEntries);
  print(empSalaryMap); // {E01: 800, E02: 20000, E03: 3000, E04: 4000, E05: 5000}
}

7. cast<RK, RV>()

Map<RK, RV> cast<RK, RV>();
Renvoyer une vue de cette Map<K,V> en tant que Map<RK,RV>.
Par exemple :
map_cast_ex1.dart
class Person {}
class Employee extends Person {
  String name;
  Employee(this.name);
}
void main() {
  var p1 = Employee('Jennifer');
  var p2 = Employee('James');
  var p3 = Employee('John');
  // int id --> Person
  Map<int, Person> personMap = {11: p1, 21: p2, 23: p3};

  Map<int, Employee> empMap = personMap.cast();
  // or
  var empMap2 = personMap.cast<int, Employee>();

  Iterable<Employee> emps = empMap.values;
  for (var emp in emps) {
    print(emp.name);
  }
}

8. castFrom<K, V, K2, V2>(..)

static Map<K2, V2> castFrom<K, V, K2, V2>(Map<K, V> source) => CastMap<K, V, K2, V2>(source);
Une méthode statique qui renvoie une vue d'un Map<K,V> en tant que Map<RK,RV>.
Par exemple :
map_castFrom_ex1.dart
class Person {}
class Employee extends Person {
  String name;
  Employee(this.name);
}

void main() {
  var p1 = Employee('Jennifer');
  var p2 = Employee('James');
  var p3 = Employee('John');
  // int id --> Person
  Map<int, Person> personMap = {11: p1, 21: p2, 23: p3};

  Map<int, Employee> empMap = Map.castFrom(personMap);
  // or
  var empMap2 = Map.castFrom<int, Person, int, Employee>(personMap);

  Iterable<Employee> emps = empMap2.values;
  for (var emp in emps) {
    print(emp.name);
  }
}

9. clear()

void clear();
Supprimer tous les mappages contenus dans Map.
map_clear_ex1.dart
void main() {
  Map<String, String> phonebook = {'01000005': 'Tom', '01000002': 'Jerry'};
  print(phonebook);
  phonebook.clear();
  print(' --- after clear() --- ');
  print(phonebook);
}
Output:
{01000005: Tom, 01000002: Jerry}
 --- after clear() ---
{}

10. containsKey(Object? key)

bool containsKey(Object? key);
Vérifier si une clef spécifiée existe dans cette Map.
Par exemple :
map_containsKey_ex1.dart
void main() {
  var phonebook = <String, String>{'01000005': 'Tom', '01000002': 'Jerry'};
  var key1 = '99999999';
  var contains1 = phonebook.containsKey(key1); // false
  print('contains key ${key1}?  ${contains1}');

  var key2 = '01000005';
  var contains2 = phonebook.containsKey(key2); // true
  print('contains key ${key2}?  ${contains2}');
}
Output:
contains key 99999999?  false
contains key 01000005?  true

11. containsValue(Object? value)

bool containsValue(Object? value);
Vérifier si une valeur spécifiée existe dans cette Map.
Par exemple :
map_containsValue_ex1.dart
void main() {
  Map<String, String> phonebook = {
    '01000005': 'Tom',
    '01000002': 'Jerry',
    '01000003': 'Tom'
  };
  print(phonebook.containsValue('Tom')); // true
  print(phonebook.containsValue('Donald')); // false
}

12. forEach(..)

void forEach(void action(K key, V value));
Convoquer la fonction d'action pour chaque clef et valeur de paire de cette Map.
Par exemple :
map_forEach_ex1.dart
void main() {
  // Employee Number --> Salary
  // Map<String,int>
  var empSalaryMap = {
    'E01': 1200,
    'E02': 2000,
    'E03': 1500
  };
  // A Closure
  var action = (String empNumber, int salary) {
    print('Emp Number: $empNumber, salary: $salary');
  };
  empSalaryMap.forEach(action);
}
Output:
Emp Number: E01, salary: 1200
Emp Number: E02, salary: 2000
Emp Number: E03, salary: 1500

13. putIfAbsent(..)

V putIfAbsent(K key, V ifAbsent());
Ajouter un mappage à cette Map si la clef spécifiée n'existe pas encore, sinon, aucune action n'est entreprise.
map_putIfAbsent_ex1.dart
void main() {
  Map<String, int> scores = {'Bob': 36};
  for (var key in ['Bob', 'Rohan', 'Sophena']) {
    scores.putIfAbsent(key, () => key.length);
  }
  print(scores['Bob']); // 36
  print(scores['Rohan']); //  5
  print(scores['Sophena']); //  7
}

14. remove(Object? key)

V? remove(Object? key);
Supprimer le mappage correspondant à la clef spécifiée.
Par exemple :
map_remove_ex1.dart
void main() {
  // Employee Number --> Salary
  // Map<String,int>
  var empSalaryMap = {
    'E01': 1200,
    'E02': 2000,
    'E03': 1500
  };
  var salary = empSalaryMap.remove('E02');
  print('Salary: $salary'); // 2000
  print(empSalaryMap); // {E01: 1200, E03: 1500}
}

15. removeWhere(..)

void removeWhere(bool test(K key, V value));
Supprimer tous les mappages qui réussissent le test par la fonction spécifiée.
Exemple : Une Map<String,int> contient les mappages entre le code de l'employé et le salaire. Supprimer tous les mappages avec un salaire inférieur à 2000.
map_removeWhere_ex1.dart
void main() {
  // Employee Number --> Salary
  // Map<String,int>
  Map<String,int> empSalaryMap = {
    'E01': 1200,
    'E02': 2000,
    'E03': 1500,
    'E04': 1700,
    'E05': 5500
  };
  // A Closure
  var test = (String empNumber, int salary) {
    return salary < 2000;
  };
  empSalaryMap.removeWhere(test);
  print(empSalaryMap); // {E02: 2000, E05: 5500}
}
Output:
{E02: 2000, E05: 5500}

16. update(..)

V update(
    K key,
    V update( V value ),
    {V ifAbsent( )?} // Optional Named Parameter
)
Mettre à jour une nouvelle valeur pour la clef spécifiée.
  • Si la clef spécifiée existe déjà dans cette Map, la nouvelle valeur sera calculée par la fonction de update fournie.
  • Si la clef spécifiée n'existe pas dans cette Map, la fonction ifAbsent sera utilisée pour calculer la valeur, ou null si la fonction ifAbsent n'est pas fournie.
Par exemple :
map_update_ex1.dart
void main() {
  // Employee Number --> Salary
  // Map<String,int>
  var empSalaryMap =  {
    'E01': 1500,
    'E02': 2500,
    'E03': 3500
  };
  for(var key in ['E02', 'E05', 'E07']) {
      var newValue = empSalaryMap.update(key,
                                      (value)   {
                                          return value * 2;
                                      },  
                                      ifAbsent: () => 111 // Named Optional Parameter.
                                  );
  }
  print(empSalaryMap); // {E01: 1500, E02: 5000, E03: 3500, E05: 111, E07: 111}
}
Output:
{E01: 1500, E02: 5000, E03: 3500, E05: 111, E07: 111}

17. updateAll(..)

void updateAll(V update(K key, V value));
Mettre à jour toutes les valeurs de cette Map, avec les nouvelles valeurs calculées par la fonction de update fournie.
Par exemple : Une Map<String,int> contient les mappages entre le code de l'employé et le salaire. Utiliser la méthode updateAll pour mettre à jour le double salaire s'il est inférieur à 1000.
map_updateAll_ex1.dart
void main() {
  // Employee Number --> Salary
  // Map<String,int>
  var empSalaryMap = {
    'E01': 800,
    'E02': 20000,
    'E03': 700
  };
  // A Closure
  var update = (String empNumber, int salary) {
    if (salary < 1000) {
      return salary * 2;
    }
    return salary;
  };
  empSalaryMap.updateAll(update);
  print(empSalaryMap); // {E01: 1600, E02: 20000, E03: 1400}
}
Output:
{E01: 1600, E02: 20000, E03: 1400}