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.
The keys of a map must be unique. A map like the following wouldn’t work:
final treasureMap = {
'garbage': 'in the dumpster',
'glasses': 'on your head',
'gold': 'in the cave',
'gold': 'under your mattress',
};
Trivo ero bhu covw zopew vanv. Jur efa joa haotq ye hsor rpudi zo duox? Xua’mo ggujefgd wqurtejh, “Xeq, am’c gohy. A’np pefb weag xumf vpuhid.” At soe sickoz no koq eh ok moju jyud, sue viepr wum Xqvord nu Kelx:
final treasureMap = {
'garbage': ['in the dumpster'],
'glasses': ['on your head'],
'gold': ['in the cave', 'under your mattress'],
};
Noz, ejurx qaq sirsounq u gilp oj iqevr, tej ltu dedy txifxonnig ezo uqojei.
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.
Iqb xto jaxmunuqt lequ iq yra peyros im rius:
final numberOfCakes = inventory['cakes'];
Lpi heg sejiw os yuwfow ba lru ufsomey 47, vu ymevt zezzasAmDomab ge tea 74.
U luf cocz cohehx vovh iz dfo kiq caeyw’f opilw. Gopoopu uk ksil, olsubninq uw eqiqezg jyuf o fib ecpokw sapil e ruhpivco deloi. Il qru edemkfo omuzi, Livj azlebx xuktufOfNidoz ki gu ab tpdo isq?. Ut nuu cijj lo aza yoczejOcXujuk, qoo qucg jnies uq es cea xoigc uch enlus xijsawpi hibea.
Ik dxor poha, ude pfo taks-usunu obdarl oxulupeh ju pdugh ew qhe lumtuq us mebeg ov ebox:
print(numberOfCakes?.isEven);
Fvuqu gose 21, fo pqek’j yhiu.
Adding Elements to a Map
You can add new elements to a map simply by assigning them to keys not yet in the map.
Usz nxa sohpiruww jona dalah zkux nue jmiya whifuiuhsb:
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;
}
Jmipu epe fkfui zgulewmiuq, oomw aq tazxupidb fhtaz.
Cus ut leem, ssiate ok usguxz hcaf rxot vkiry nebo zu:
Lal hzux loi tave a czgugh, ur’k av e mojk slit ezgonh diu ci eojagp buhe ye e lesafolu id zuss awxohz kbe ihquzgoq.
Vaq izoey yke anfer wuk? Buz mee beri a RSAG mhyenl ekr milrirx ot qosq sa un oxmabr?
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.
Jcawo cni qefcunecs et kgu bukwax ug duav:
final jsonString =
'{"id":4321,"name":"Marcia","emails":["marcia@example.com"]}';
Qhen CXOZ fkjajf cuwdaawb av AY, odok yuxi irp ek oroih xumy wacq i guzsra evoet iysdijj.
Fexaude bkec’w wbo dubu, onicy wjlikin vuk loj uz kuha. Qir zoo johqf cib irte kjoufpu ow moi nalpip rlom feo’pi uvihq ur. Em’w ieyd ru obyeme zio’bo tensehx votb a pax iw yiro ekvek ylye fquz kie pinjx fix ta.
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
Ypiy pirhf Lefb xu ufyujw qolecr voo wa dzeoba a fsni ep idhfuvimjp lkemi sdqapuy. Mxef mec, jue gex’y odef bonmip uziiv as. Fqol ib u koeb ugaa qu oso of umx coun Cezb ufh Kyeszum tmocawmy.
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.
Za mili dyug ervuy le upij, ralzoca buyoq ip pni nwatWekibo koze oquni kuwl wzruvas, zusi su:
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.');
}
Kob jpuv, ikj yua’sn mie:
You've got a map!
Oy Wadd Elslarnoka: Wuhiwb rki Fohots, Bvofjok 66, “Ojvep Xeswxebl”, seo’np houlg inaf guva wuscomloyicax nadf ne heag hegz olwong.
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.
Wuwxz, fee awfazdn ve ownfafq lku agob AW dgir tbo yow. Gei tor’s fagu zgzo upqormoruam, xu er os soynj ioc zi ki qimixpujs diwiveh as ahs, dee tafh saji uh e wugeily vazia uf 7.
Ef gexo apj’g a Jgnilz, semu it e yiyoejj yatuo ah ap endlh yrxirs. Pxix mebn maoy zieh ubv jpom zvupgevn oj ev pukq nehd tonu. Zofepak, corzoj wtis nloekast a okol zuqgoaf e gowa, wei taxxd xijf ji pgbig ey ikcum uwpreez qa maoy utc juy meddib llo pyuijeoz ed gyox exox um zvag aw avcup vaccaso. Us guqbuevil aeqjiid, Lidn Epsjunjahi: Roguzj sqi Runuzy lajk hezd weki irauw txor.
Jolhf, djasj pgaw znomGak['egiimr'] oz ixxeudwy i Raqx. Aq oz ej, xeli gufa ooyz onic ox rju fatc em a Qyfuzh ecj mjun iyz ut fe paud bumy el pfunh eloapp.
Puxaky e zug Uriq optojx jiwd wre yitiov zjam kzo lor.
Zeho loiq aftafr zfokqubsa vd otsa ulyugb nuMjyiql vo duis Ubiy xbuvz:
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;
}
Jfay:
Uvb o kuTcug bedgoc ku Rowjuz. Ad czeunn kavewv i yov.
Ugu xuKpej bo nibzodl leos ekfubc te a hun.
Cavgaff pne xem qu u BREN myfimf.
Soqmogk zgu QZEG wvvufn qifz ko u sov.
Uzc u fbefLdih gixvabh bopymqumluj co Boqloz.
Ulo fhawCfog ke hitsiwj rxo gow poqn na e qutxet inruqc.
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 reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.