Tabla de Contenido
- Tabla de Contenido
- Introducción
- Mapas (Maps)
- Conclusión
- Fuentes
Introducción
Ya vimos tanto las listas como los conjuntos en Dart, además de sus constructores, propiedades y métodos que son compartidos entre ellos. Ahora veremos qué son los Mapas (Maps) y cómo se utilizan en Dart.
Mapas (Maps)
Los Maps son otro tipo de colección así como lo son los Lists y Sets, se puede decir que son similares a los Sets, solo que trabajar con llave (key) y valor (value), cada valor va asociado a una llave que designemos. Tanto las claves como los valores pueden ser de cualquier tipo, las claves son únicas pero los valores si se pueden repetir.
Constructores de mapas (Maps)
A continuación, veremos los constructores que se pueden utilizar en Dart para crear Mapas.
Se pueden crear Mapas (Maps) con literales o con métodos como veremos a continuación.
Literales
Crea un **Map** si especificar un constructor.
void main() {
var colors = {
2: 'red',
10: 'green',
18: 'blue',
};
print(colors); // {2: red, 10: green, 18: blue}
}
Constructor Map<K, V>
Crea un **Map** vacío.
// estructura del constructor
// Map<K, V>
// K: tipo de dato de la llave, V tipo de dato del valor
void main() {
var letters = Map<int, String>();
letters[0] = 'A';
letters[1] = 'B';
letters[2] = 'C';
print(letters); // {0: A, 1: B, 2: C}
}
Constructor Map<K, V>.from
Crea un **Map** con las mismas claves y valores que el enviado como parámetro.
Es preferible utilizar Map.of siempre que sea posible, y sólo utilizar Map.from para crear un nuevo mapa con tipos más precisos que el original, y cuando se sepa que todas las claves y valores tienen esos tipos más precisos.
// estructura del constructor
// K: tipo de dato de la llave, V tipo de dato del valor
// other: Map con el que se va a crear otro.
Map<K, V>.from(
Map other
)
// Ejemplo
void main() {
var countries = {'COL': 'Colombia', 'BRA': 'Brasil', 'PTR': 'Portugal'};
var countriesMap = Map<String, String>.from(countries);
print(countriesMap); // {COL: Colombia, BRA: Brasil, PTR: Portugal}
}
Constructor Map<K, V>.fromEntries
Crea un nuevo **Map** y añade todas las entradas (los datos llave — valor enviados como parámetro). En caso de añadir más adelante otro valor con una llave existente, se reemplaza la el valor anterior con el nuevo.
// estructura del constructor
// K: tipo de dato de la llave, V tipo de dato del valor
// entries: iterable con entradas de Maps.
Map<K, V>.fromEntries(
Iterable<MapEntry<K, V>> entries
)
void main() {
var countries = <String, int>{'COL': 1, 'BRA': 3, 'PTR': 5};
final fromEntriesMap = Map.fromEntries(countries.entries);
fromEntriesMap.addAll(<String, int>{'COL': 3});
print(fromEntriesMap); // {COL: 3, BRA: 3, PTR: 5}
}
Constructor Map<K, V>.fromIterable
Crea una instancia de **Map** en la que las claves y los valores se calculan a partir del iterable.
// estructura del constructor
// K: tipo de dato de la llave, V tipo de dato del valor
Map<K, V>.fromIterable(
Iterable iterable,
{K key(
dynamic element
)?,
V value(
dynamic element
)?}
)
// ejemplo
void main() {
final numbers = <int>[1, 2, 3, 4, 5];
final map = Map.fromIterable(numbers);
print(map); // {1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
}
Constructor Map<K, V>.fromIterables
Crea un **Map** que asocia las claves dadas a los valores dados. Esto quiere decir que tanto sus llaves como sus valores se reciben por parámetros y con esto arma el **Map**.
// estructura del constructor
// K: tipo de dato de la llave, V tipo de dato del valor
// Iterable<K>: son las claves del nuevo Map.
// Iterable<V>: son los valores del nuevo Map.
Map<K, V>.fromIterables(
Iterable<K> keys,
Iterable<V> values
)
// Ejemplo
void main() {
final values = <bool>[true, false, false, true];
final keys = <String>{'Apple', 'Lemon', 'Cherry', 'Pear'};
final map = Map<String, bool>.fromIterables(keys, values);
print(map); // {Apple: true, Lemon: false, Cherry: false, Pear: true}
}
Constructor Map<K, V>.identity
Crea un mapa de identidad con la implementación por defecto.
// estructura del constructor
// K: tipo de dato de la llave, V tipo de dato del valor
Map<K, V>.identity()
// ejemplo
void main() {
var identityMap = Map.identity();
identityMap.addAll({'Apple': true, 'Cherry': false});
print(identityMap); // {Apple: true, Cherry: false}
}
Constructor Map<K, V>.of
Crea un **Map** con las mismas claves y valores que el enviado por parámetro. Este constructor es recomendable sobre el Map.from.
// estructura del constructor
// K: tipo de dato de la llave, V tipo de dato del valor
// other: Map con el que se va a crear otro.
Map<K, V>.of(
Map<K, V> other
)
// ejemplo
void main() {
final animals = <int, String>{1: 'Lion', 2: 'Tiger', 3: 'Monkey'};
final mapOf = Map<num, String>.of(animals);
print(mapOf); // {1: Lion, 2: Tiger, 3: Monkey}
}
Constructor Map<K, V>.unmodifiable
Crea un mapa no modificable basado en hash que contiene las entradas del **Map** recibido por parámetro.
// estructura del constructor
// K: tipo de dato de la llave, V tipo de dato del valor
// other: Map con el que se va a crear otro.
Map<K, V>.unmodifiable(
Map other
)
// ejemplo
void main() {
final animals = <int, String>{1: 'Lion', 2: 'Tiger', 3: 'Monkey'};
final unmodifiableMap = Map.unmodifiable(animals);
// Uncaught Error: Unsupported operation: Cannot modify unmodifiable map
unmodifiableMap[4] = 'Bee';
}
Propiedades de un Mapa (Map)
Veremos a continuación, las propiedades que traen los **Maps** en Dart.
void main() {
final animals = <int, String>{1: 'Lion', 2: 'Tiger', 3: 'Monkey', 4: 'Bee'};
// entries → Iterable<MapEntry<K, V>>
// obtiene las entradas del mapa.
// (MapEntry(1: Lion), MapEntry(2: Tiger), MapEntry(3: Monkey), MapEntry(4: Bee))
print(animals.entries);
// hashCode → int
// obtiene el identificador hash para el Map. Cambia por cada ejecución.
print(animals.hashCode);
// isEmpty → bool
// Valida si el Map está vació.
print(animals.isEmpty); // true o false
// isNotEmpty → bool
// Valida si el Map tiene al menos un par clave/valor.
print(animals.isNotEmpty); // true o false
// keys → Iterable<K>
// obtiene las llaves del Map. como Iterable.
print(animals.keys); // (1, 2, 3, 4)
// length → int
// devuelve el tamaño del Map.
print(animals.length); // 4
// runtimeType → Type
// devuelve el tipo de objeto en tiempo de ejecución.
print(animals.runtimeType); // JsLinkedHashMap<int, String>
// values → Iterable<V>
// obtiene los valores del Map. como Iterable.
print(animals.values); // (Lion, Tiger, Monkey, Bee)
}
Métodos de un Mapa (Map)
A continuación, los métodos que podemos utilizar con los **Maps**.
void main() {
final animals = <int, String>{1: 'Lion', 2: 'Tiger', 3: 'Monkey', 4: 'Bee'};
// addAll(Map<K, V> other) → void
// Agrega más pares llave/valor al Map.
// Si la clave ya existe en el mapa se sobreescribe el valor.
animals.addAll({4: 'Spider', 5: 'Eagle'});
print(animals); // {1: Lion, 2: Tiger, 3: Monkey, 4: Spider, 5: Eagle}
// addEntries(Iterable<MapEntry<K, V>> newEntries) → void
// Agrega todos los pares clave/valor de newEntries en animals.
final newEntries = <int, String>{6: 'Bee'};
animals.addEntries(newEntries.entries);
print(animals); // {1: Lion, 2: Tiger, 3: Monkey, 4: Spider, 5: Eagle, 6: Bee}
// cast<RK, RV>() → Map<RK, RV>
// provee una vist del Map.
print(animals.cast()); // {1: Lion, 2: Tiger, 3: Monkey, 4: Spider, 5: Eagle, 6: Bee}
// clear() → void
// elimina todos los pares del Map.
animals.clear();
print(animals); // {}
final newAnimals = <int, String>{1: 'Lion', 2: 'Tiger', 3: 'Monkey', 4: 'Bee'};
// containsKey(Object? key) → bool
// busca el par por medio de la clave, si existe true, sino false.
print(newAnimals.containsKey(4)); // true
// containsValue(Object? value) → bool
// busca el par por medio del valor, si existe true, sino false.
print(newAnimals.containsValue('Tiger')); // true
// forEach(void action(K key, V value)) → void
// Se recorren todos los pares clave/valor.
newAnimals.forEach((key, value) => print('$key - $value'));
// 1 - Lion
// 2 - Tiger
// 3 - Monkey
// 4 - Bee
// map<K2, V2>(MapEntry<K2, V2> convert(K key, V value)) → Map<K2, V2>
// Devuelve un nuevo mapa donde todas las entradas de este mapa
// se transforman mediante la función de conversión dada.
// noSuchMethod(Invocation invocation) → dynamic
// Se invoca cuando se accede a un método o propiedad inexistente.
// putIfAbsent(K key, V ifAbsent()) → V
// Busca el valor de la clave o agregue una nueva entrada si no está allí.
print(newAnimals.putIfAbsent(4, () => 'New')); // Bee
// remove(Object? key) → V?
// Elimina clave y valor asociados a la clave ingresada.
print(newAnimals.remove(4)); // Bee
print(newAnimals); // {1: Lion, 2: Tiger, 3: Monkey}
// removeWhere(bool test(K key, V value)) → void
// Elimina clave y valor cuando se cumple la condición.
newAnimals.removeWhere((key, value) => key > 2);
print(newAnimals); // {1: Lion, 2: Tiger}
// toString() → String
// devuelve una representación de string.
print(newAnimals.toString()); // {1: Lion, 2: Tiger}
// update(K key, V update(V value), {V ifAbsent()?}) → V
// Actualiza el valor de la clave proporcionada.
// Devuelve el nuevo valor asociado con la clave.
// Si la clave está presente, invoca la actualización con el valor actual y
// almacena el nuevo valor en el mapa. Si la clave no está presente
// y se proporciona ifAbsent, llama a ifAbsent y agrega la clave con el valor devuelto
// al mapa. Si la clave no está presente, se debe proporcionar ifAbsent.
print(newAnimals..update(1, (value) => 'Bee')); // {1: Bee, 2: Tiger}
print(newAnimals..update(3, (value) => 'Lion', ifAbsent: () => 'Spider'));
// {1: Bee, 2: Tiger, 3: Spider}
// updateAll(V update(K key, V value)) → void
// Actualiza todos los valores teniendo en cuenta la función que se pasa.
newAnimals..updateAll((key, value) => value.toUpperCase());
print(newAnimals); // {1: BEE, 2: TIGER, 3: SPIDER}
}
Conclusión
Podemos concluir el tema de las colecciones en Dart, vimos un poco a profundidad los constructores, propiedades y métodos de las 3 colecciones que nos da soporte Dart, ya depende de cada caso saber cuál es la mejor opción para utilizar.
¡Gracias por leer!
