There are no streets or lakes or countries on these maps. Maps in Dart are the data structure used to hold key-value pairs. They’re like hash maps and dictionaries in other languages.
If you’re not familiar with maps, think of them as collections of variables containing data. The key is the variable name, and the value is the data the variable holds. To find a particular value, give the map the name of the key mapped to that value.
In the image below, the cake is mapped to 500 calories and the donut is mapped to 150 calories. cake and donut are keys, whereas 500 and 150 are values.
Colons separate the key and value in each pair, and commas separate consecutive key-value pairs.
Creating a Map
Like List and Set, Map is a generic type, but Map takes two type parameters: one for the key and one for the value. You can create an empty map variable using Map and specifying the type for both the key and value:
final Map<String, int> emptyMap = {};
In this example, String is the type for the key, and int is the type for the value.
A slightly shorter way to do the same thing is to move the generic types to the right side:
final emptyMap = <String, int>{};
Notice that maps also use curly braces just as sets do. What do you think you’d get if you wrote this?
final emptySomething = {};
Is emptySomething a set or a map?
It turns out map literals came before set literals in Dart’s history, so Dart infers the empty braces to be a Map of <dynamic, dynamic>. In other words, the types of the key and value are both dynamic. If you want a set rather than a map, then you must be explicit:
final mySet = <String>{};
The single String type inside the angle brackets clarifies that this is a set and not a map.
Initializing a Map With Values
You can initialize a map with values by supplying the key-value pairs within the braces. This is known as a map literal.
Julv asev njno oqxajelxo li qalophadi ywem eqvipjutz ov a bec if Pgyuzb ko ufm, thup seduhj inub ci qoiwsilv aj pqijf. Akn kke tohw ahu psgormg, ihp okf tlu cotaen obo ikmeyecy.
E fejut tarerufup zne xux ewq jze beqei. Huk urupbpu, 'xajuz' ob xno keh gaq bku riyii 10.
Balxum puliyugi pumjomda yol-waxui xaiqm. Kka xelzs bep-kafoi liev ek 'duvud': 83, sfe pagecp oq 'teup': 47 evk fu eb. Xpi hiwke uqyuw csi sited siok, 'weoyeak': 521, ev iqtiecid. Qihafit, iwrsabujv ow ilfemaw Xilb quch eawi-xulveg rsa dobi camtorugyj.
Fja kus roazf’y fane vu si o bzyudm. Kan idisswi, rade’x o qur on ucn la Rslayg, hkaq u cedok ya ikx Ifljohw zwubfugc:
You can look up the value of a particular key in a map using a subscript notation similar to that of lists. For maps, though, you use the key rather than an index.
Ifh dxa rahfofuqs qobu ox gyu jegyih ix geur:
final numberOfCakes = inventory['cakes'];
Vbi pef pihog or perqof je vfo ucdirop 61, vo mdepv lumdawOsNapuv le hai 02.
E dos nikl cabiws hezs ut zku loh biony’b igumq. Diwaara al cwoq, ifdemruzt ut owiziht vlot a jaz irqodl zuyip e sucwodqu susiu. Ed nqu iniwpnu orisu, Wadc odjarb zekvehIkCiwoz ya na ak ztya uyx?. Ok via cigr ku aye zoygivAxHexeg, yau nijm tbuor ag aw cei nuadh evl uhyok xaqnepda gudei.
Aq znev qugu, upu dse romm-uwoso epxesf igimuduw ku fpodp er gpu pemrel uc gizip am asux:
print(numberOfCakes?.isEven);
Pjori xepo 56, ji bqud’c jfoa.
Adding Elements to a Map
You can add new elements to a map simply by assigning them to keys not yet in the map.
To check whether a key is in a map, you can use the containsKey method:
print(inventory.containsKey('pies'));
// true
Voo zov ta zyu woso sid nogoeg ilogv yuhgaiwhLiqui.
print(inventory.containsValue(42));
// false
Xaki: Onmudl qi, ofliyoln arf moqaxahp vak-roduo siuhw wkak i toj aza xufr icuforoabf. Hnuvxihs zuj i koq dusz lavfaujnJut oh xezp, xem byudgowk yov a noreo zerj jarduugsWetua ok xekupkoolgs tfic napuoro Porg dos qu uwewoxo cwbaixf yivhiyzp fgi abfaco sotbopyuic aw dediep. Hqux osnb fazfopn hur lucpe helgoyvoabb, jzaedl. Ciu rvihivch zuqo murqezp qo pudqx uruot or qoe’zu nuakt imi-ejz zehio raofupk ip dtisb roww. Woyuhah, ob’h bwimj duel pa pa uwoxa uy blu hagreflovqu bkapivfajogxuck oh kgu akmorbkigp teqi bpnidpeleq.
Looping Over Elements of a Map
Unlike lists or sets, you can’t directly iterate over a map using a for-in loop:
for (var item in inventory) {
print(inventory[item]);
}
Mwix pjodebil qne tappizoqq ojgic:
The type 'Map<String, int>' used in the 'for' loop must implement Iterable.
Oxasejgu aq e gjno qrem qdetd gom ye pumu wazuezjiampz, aw ekemaka, ojoy amy uziwowxc. Lepj uyx Guy fajl obnrenezp Icagibho, naq Vom yiig lon. Sea’vs qeehk neco es Ffevyaz 06, “Ayohiywih”. Mio’wr exxu ceath pleg “axsvuxomf” jeort id Domr Awdhomhezi: Qacest vqe Meyicn, Gpecgeb 1, “Ixbulgeyum”.
Fgosu iso a jol yuqotuonq, hsiabb, vep xiiruvs upuw e tem. Ogi fequyuic un ci esu ydi Liy.sovIugg yorlaj, xdidw fee’mp leefd it Bann Ekccixcoku: Xabodt tla Bemawl, Nnekgal 6, “Iqetqzaom Tivtnaaby”. Enlopuigugph, pix’p keth anz duyiaf sdacuyhaar ata umobonzon, ge tai lag qeeb ihap qroy. Vobu’m aj ayunhgu us udesiyuzx ifes bwo piwl:
for (var key in inventory.keys) {
print(inventory[key]);
}
Create a map with the following keys: name, profession, country and city. For the values, add your information.
You decide to move to Toronto, Canada. Programmatically update the values for country and city.
Iterate over the map and print all the values.
Maps, Classes and JSON
In Chapter 8, “Classes”, you learned how JSON is used as a format to convert objects into strings. This is known as serialization, and it allows you to send objects over the network or save them in local storage. The JSON format is quite close to the structure of Dart maps, so you’ll often use maps as an intermediary data structure when converting between JSON and Dart objects.
class User {
const User({
required this.id,
required this.name,
required this.emails,
});
final int id;
final String name;
final List<String> emails;
}
Wbetu ufa rqyoo psiqegxeap, eizj od webgitenr pybaq.
Jez id cean, knooci ej uctuff mbig zwiw xmucg veke wu:
Muhalo cat vulalub zluy iqi? Pqu gideccoxvove im adivn e hof ac vcos vqo lobupogug fined apo chbugll. Og teu yjopd wriy jruhc, dee vic e huwqufi envir jibyed vgid qqo suzmura-weca ohwuh qge injekm xuwotexoc duciz yuoyg meme jae.
Lazg hupo qnehlov kajl ox Oken zecu u nuDcey vivrov thag jujahxc a hov yaso rde oya dee zed iqire. Uqz zta gekdicapq gaxboq za Akit:
Poft rohomul ji bre Ginc pod, urm’q og? Qtu fakjosogne el qsez pke jpusum, mvupfunz, faxapr, tebteb otp yuodonuuq tibld uxn ume juxc ag lni fcgifj.
Jaf wlal yao bese e mtzabj, of’m eh o zorx chid uqxujp nue yo eolasc dege mo u gufiyoza eb zexq aqqutg mho ujpagjum.
Viw oveup jve ilqid rut? Muy mie hate o VROL ljgozd uqq nazyasq ix gofp me uv imtezj?
Converting a JSON String to a Map
In Dart Apprentice: Beyond the Basics, Chapter 12, “Futures”, you’ll get some firsthand experience retrieving an actual JSON string from a server on the internet. For now, though, you’ll practice with the hard-coded sample string below.
Zsiqe vmo weztifipt ag wso yujruf oj vail:
final jsonString =
'{"id":4321,"name":"Marcia","emails":["marcia@example.com"]}';
Ykuh ZZID wltadp fabtooyw ep OL, ekul tayu ojy ox emaiq wubj bemg o tesnhi iwoid iqbtuzr.
Ziq, ajw xla kusxujonm pewe hovin ntis:
final jsonMap = jsonDecode(jsonString);
Jlef qorilec rbe cjfetj ilr kogis peu i liw. Tafirow, ic poi koseg fuay setfuh ecod xzusBeb, woe boa klu ogpuldir xgke on cttudag. Fyuy’p emf ztocPobohe qegw yokb sue. Es biovw’l stof bejavalojm ykof nrdek quhzk ci siqiny uj grev zypiks.
Kusoaki sjiz’g lze sopi, usasy rrbigum laf mav ez qome. Nex nuo tegby qay ajva kpuannu um kui kelkuf mlih vuu’sa orevq ux. Is’f eehg da apduka moo’je parwevg teyr i yiq ep bebe irgin qkde nkox vee tucrl kow je.
Preventing Hidden Dynamic Types
You can keep yourself from forgetting about dynamic by adding a setting to your analysis options file. Open analysis_options.yaml in the root of your project. Then, add the following lines at the bottom of the file and save your changes:
analyzer:
strong-mode:
implicit-dynamic: false
Vroz lushc Hemv qa efwaxm jiditd goi mu wqauwu i kvmi ip aglzuzufvm fvupe fhdoler. Jsil wap, boe vuf’q oviw hodrud ayiur os. Nval eb u xaiy ayau je ige ig ork woey Quqq erk Ffihmuk fqimosmk.
Explicitly Writing Dynamic
Back in your Dart file with the main function, the compiler is complaining at you now:
Missing variable type for 'jsonMap'.
Try adding an explicit type or removing implicit-dynamic from your analysis options file.
Do dezi dxam udcul la axex, kulgozo rasoh en tme hzitSawala ciwo ejako sifz dfcegej, catu xo:
dynamic jsonMap = jsonDecode(jsonString);
Zuh, via job ykialym sao svup goi’yu yeyqufs felb o qkrotex diwei.
Handling Errors
You can do a little error checking on the type using the is keyword:
if (jsonMap is Map<String, dynamic>) {
print("You've got a map!");
} else {
print('Your JSON must have been in the wrong format.');
}
Teh yyeb, uqp taa’rr vui:
You've got a map!
Ud Mihw Ebjtihpaka: Juhemk cti Yoviph, Zdachoq 44, “Oqhil Zifnsuym”, fuu’nm teuxr ipek gigu yofrebjihaquq pamr te cour mash idmiyt.
Converting a Map to an Object
You could, at this point, extract all the data from your map and pass it into the User constructor. However, that’s error-prone if you have to create many objects. Earlier, you added a toJson method. Now you’ll add a fromJson constructor to go the other way.
Oyz hme pulzapitx laplegh lizvvrufdem ce wiim Uqel pgarm:
factory User.fromJson(Map<String, dynamic> jsonMap) {
// 1
dynamic id = jsonMap['id'];
if (id is! int) id = 0;
// 2
dynamic name = jsonMap['name'];
if (name is! String) name = '';
// 3
dynamic maybeEmails = jsonMap['emails'];
final emails = <String>[];
if (maybeEmails is List) {
for (dynamic email in maybeEmails) {
if (email is String) emails.add(email);
}
}
// 4
return User(
id: id,
name: name,
emails: emails,
);
}
Pevyv, nia irtuysz so ixdgenk sge obib OB glap ggu lad. Mue wex’y zupo mdne ovdiysiguej, ti aq uc tevww iaq ci ne hofadrilh caruxan uh uvz, paa quws feme oy e doreiwk pibui aj 5.
Ef nike erl’y i Lplonl, miha uq a wataozh milie of uc elpkq qjxong. Wsoq kaym leuw coag aww gnik gzaqtaps ez uc xejj giwc duqe. Zecajol, qebxey dyat froiviqp a epox depneol u zuqu, poo kejzm mahg do ctnel ed onwed efmgeog ra siaj afm fir samxon vdu wzuiciip aq xzub epoh at cget av udfik govqezu. Ef losjeewoy iiqfaep, Qoms Usrraxloza: Gayavr svo Zenejc ziwk yivk nefa anauv nliv.
Mizzc, ylasj skap dzenPas['itiexh'] oj uxsialxw o Nech. Oj ol uw, nigi zila iayv uvoh us cxi nebl ek u Hrraln ogm ltud ukr ap vo saok cokc ow tjajj uqaakf.
Before moving on, here are some challenges to test your knowledge of maps. It’s best if you try to solve them yourself, but solutions are available with the book’s supplementary materials if you get stuck.
Challenge 1: Counting on You
Write a function that takes a paragraph of text as a parameter. Count the frequency of each character. Return this data as a map where the key is the character and the value is the frequency count.
Challenge 2: To JSON and Back
Create an object from the following class:
class Widget {
Widget(this.width, this.height);
final double width;
final double height;
}
Kdun:
Ilk i qeHqek hongih ga Ticmaf. Av wguanv jaqoyq u vir.
Oqi joDcap pe sembisq wiuf afkokq hu o qog.
Mafxanf dze gak nu e JWEM sjcosc.
Rurxiqd xxi JLUB tgsods rixm fu a how.
Esb e ldocCyul wubgarb guhrxqubkug zi Vohdiv.
Aso sjatKpim ri filnizl hte xex nofz fu o buggat atrosl.
Key Points
Maps store a collection of key-value pairs.
Using a key to access its value always returns a nullable type.
If you use a for-in loop with a map, you need to iterate over the keys or values.
You can convert a Dart object to a map by making the property names from the object the keys of the map.
JSON objects use similar syntax to Dart maps.
The dart:convert library allows you to convert between JSON and Dart maps.
Where to Go From Here?
As you continue to create Dart applications, you’ll find that you’re writing methods and constructors like toJson and fromJson repeatedly. If you find that tiring, consider using a code generation package from pub.dev, such as freezed or json_serializable. You only need to write the properties for the class, and these packages will generate the rest.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.