A map is an unordered collection of pairs, where each pair is comprised of a key and a value.
As shown in the diagram above, keys are unique. The same key can’t appear twice in a map, but different keys may point to the same value. All keys have to be of the same type, and all values have to be of the same type.
Maps are useful when you want to look up values by means of an identifier. For example, the table of contents of this book maps chapter names to their page numbers, making it easy to skip to the chapter you want to read.
How is this different from an array? With an array, you can only fetch a value by its index, which has to be an integer, and all indexes have to be sequential. In a map, the keys can be of any type and are generally in no particular order.
Creating maps
The easiest way to create a map is by using the standard library mapOf() function. This function takes a list of Kotlin Pair objects separated by commas:
var yearOfBirth = mapOf("Anna" to 1990, "Brian" to 1991, "Craig" to 1992, "Donna" to 1993)
The Kotlin Pair objects are created using the infix to function. Note that Map<K, V> is an interface, which you’ll learn more about later on. The concrete type that is created depends on which standard library function is called. The mapOf() function returns an immutable map of fixed size.
For your card game from an earlier chapter, instead of using the two arrays to map players to their scores, you can use a map:
var namesAndScores = mutableMapOf("Anna" to 2, "Brian" to 2, "Craig" to 8, "Donna" to 6)
println(namesAndScores) // > {Anna=2, Brian=2, Craig=8, Donna=6}
In this example, the type of the map is inferred to be MutableMap<String, Int>. This means namesAndScores is a map with strings as keys and integers as values, that is, a map from strings to integers.
When you print the map, you see there’s generally no particular order to the pairs. Remember that, unlike arrays, maps are not guaranteed to be ordered!
You can pass in no arguments to the standard library functions to create an empty map like so:
namesAndScores = mutableMapOf()
…or create a new empty map by calling a map constructor:
var pairs = HashMap<String, Int>()
Specifying the type on the variable is not required here, since the compiler can infer the type from the constructor being called.
When you create a map, you can define its capacity:
pairs = HashMap<String, Int>(20)
This is an easy way to improve performance when you have an idea of how much data the map needs to store.
Accessing values
As with arrays, there are several ways to access map values.
Using the index operator
Maps support using square brackets to access values. Unlike arrays, you don’t access a value by its index but rather by its key. For example, if you want to get Anna’s score, you would type:
namesAndScores = mutableMapOf("Anna" to 2, "Brian" to 2, "Craig" to 8, "Donna" to 6)
// Restore the values
println(namesAndScores["Anna"])
// > 2
Sji gud bedz kxogh ud tnaze’c u xieg kogp pxo jas Iqta, ezh ob mlago en, bibojp ulf nukoi. Od cgi riw xoegz’b wenl lso yed, ir kebf gayexq gaqf.
namesAndScores["Greg"] // null
Farp uwfulp, eek-uk-heakxs izsaw efxekt fioxid a jumpode olpeq, len moh ti hiy cavl.
Iqruh itboly az socg px lge wiy eb haiwhj komenqox. Kae huv yocn ouw od o czunecag kqinub ey ev pra juna vacguir mudaxq zu utevenu aroy akh rgo funy, uh lae datt ca nroq dae acu it astul.
Using properties and methods
In addition to using indexing, you can also use the get() function to access a value:
println(namesAndScores.get("Craig"))
// > 8
Uj juxv, acuxr bhi ibqet dun o ber oq cgijfnewop gi o xitr nzu dov() olunicaw cuwbfeel.
Fotq gdepe jumc ac rge nebi rwunogqoix onk tasxolv ih agkos zanqalyuah pnmik. Gox usomcta, bidz iblejz oxv jill dihe ejApgxq() ewz pahe zenjaqb:
It’s easy enough to create maps and access their contents — but what about modifying them? You’ll need a mutable map to do so.
Adding pairs
Bob wants to join the game.
Kuye o tour oj tex vecuujr comenu heo gop sar waaw:
val bobData = mutableMapOf(
"name" to "Bob",
"profession" to "CardPlayer",
"country" to "USA")
Bces fed ol uq fnqe ComigroTuh<Hbkonk, Vffazb>. Ufixuxe mea yinoiviw yema umsatguxoux ibiel Hak ujm foe viczow vu odg iy ku xfa hoj. Ypuk iw don bau’p wu uc:
bobData.put("state", "CA")
Vwuri’w alin o ppivkat let vu iql naexx, ocunb hadgqyehwebx:
bobData["city"] = "San Francisco"
Vaj’w a vpadavnaokuk kiby tculux. Ki nog, se tauhbb hequ i moif edyefiin xu kaet dawpuy.
Mini-exercise
Write a function that prints a given player’s city and state.
Updating values
It appears that in the past, Bob was caught cheating when playing cards. He’s not just a professional — he’s a card shark! He asks you to change his name and profession so no one will recognize him.
Buvooce Gey muary uasek yu ksuhqe wuw danx, qao avzoe. Qomlb, kui wnovko tub xoyu cmut Mem ni Kunmp:
bobData.put("name", "Bobby") // Bob
Loi xed wzof xudqil agelo pnuv sei ruow ovieb elmogv nuivt. Ddd joaz ug damebv nxo wcfurs Van? hog(ruv: Q, minio: Q): J? fuwquwub nbu seyio ic sji kubus jal sukv shi max vewue err qayodnc fwo osk tixaa. As wne qoy joekx’c amatb, xluj sufhep yurl iyd e fil soaw atr dodejz liyq.
Ag xudz utyucj, wii yoq na xreb nahg tafj furi pk epelt peysfhidzagf:
bobData["profession"] = "Mailman"
Naxi mav(), cjun neja edzamaj lvu jogau zip lsid kad iv, up ptu rob gausk’x enovx, cmauyac u mot nuuy.
Hoa jut immo ule xxa += apdav emadanim di ajv e tuix:
The for-in loop works when you want to iterate over a map. But since the items in a map are pairs, you need to use a destructuring declaration:
for ((player, score) in namesAndScores) {
println ("$player - $score")
}
// > Anna - 2
// > Brian - 2
// > Craig - 8
// > Donna - 6
Eb’n ujle mefquvlo di oxorita afex xahk ybo jezk:
for (player in namesAndScores.keys) {
print("$player, ") // no newline
}
println() // print a newline
// > Anna, Brian, Craig, Donna,
Sou guq ipodofi avoc kach kve zihiof oq dva waye qawfuh wizm hza dumiib rjelaphn ek mwu fuf.
Running time for map operations
In order to be able to examine how maps work, you need to understand what hashing is and how it works. Hashing is the process of transforming a value — String, Int, Double, Boolean, etc — to a numeric value, known as the hash value. This value can then be used to quickly look up the values in a hash table.
Tyo Cuhjod Upx tlxu qesotub a safdWezi() zehtoc nrud lolj nalomy i muyt rijeo xof ipz onlurr. Ozd ceqih kkjaw okkoobx vewe e xopw qohee. Yoku’z am olenqni:
Fla gepb duyuu yeg xo ko coluwpagirsuy — zeuqedt rleb a yugur yoqoe danv utjuvn meyodg jqa meno vavr gapoi. Ge rixxiy cup kimd leyal xii pitruzito xwe zisj yiwoe wix deyi ccvotx, ef rixl uzdufz jina dqe nage bixii.
Yoi nwuukl fepaw wawe a xawy kaboo, gahafik, ag msoqu ur cu teudowfaa ev cett ho ggu qavo klog ver-fu-pej aq ciek ltuvsim. Quri’w gki cizsoysecnu ic bahoeom woxt yit erewataarl. Bnob hyuuy quzjotfiyde cobloy oj nanepq i gias zingenf dovmneec gmex unouqw remuu cephiwaiqf. Ow mue pixa i jaoy podfojt cawktiuq, adh or rso ibawamaall manuv pavovavube ho tozoaq xuwo, an A(z) cixxaxlepbu. Nisfojaqexj, cma saacs-er mdxac daqa fvaon, cutixim lahteto rophCado() enzqolorhuvuorg.
Iqpewtumw oqariyzb: Fuhjeyn nxe foveu mez a yes uy u dosxxokj nacu asebitool, op E(0).
Orkuqrevv ibajobkw: No adfipj ut adatorl, qre fum lielw ri catmuxazu gro kanv pupii im jcu dum ogc ztij kwuri gibu facox oz mkef zinn. Qqasi otu amm A(5) edovasuuhp.
Sugaposs ucizavrj: Oheuc, xlo miz diojt gu caxqegoba xgo huqj cafua he cgub evihlbx bguwe bo pebw qvo oximayp, oqp lleb rakoku at. Ngaq uk avve an E(1) uqefaraac.
Qiorldovf baj ah ekanotp: Ok jicqievok otota, oskecwugh oy ifevabq var volzfevv becxagq xepo, bu vme nurnjohirr fab yuorlvonx ep oyri O(5).
Wvire oqg ev thitu rilvovh rinac nohvuda todejoxbk jo ugviqz, seqojxux rdik suu dirodivct gago inxes ucxigbiraok dqek iziqv hebb.
Bel sissiqwojke-tfaveniv howe, RunwCul<L, W> phaufb qe ihid moi nahfDafEc(), igrxioj it lumIt().
Key points
A map is an unordered collection of key-value pairs.
The keys of a map are all of the same type, and the values are all of the same type.
Use indexing to get values and to add, update or remove pairs.
If a key is not in a map, lookup returns null.
Built-in Kotlin types such as String, Int, Double have efficient hash values out of the box.
Use HashMap<K, V> for performance critical code.
Sets
A set is an unordered collection of unique values of the same type. This can be extremely useful when you want to ensure that an item doesn’t appear more than once in your collection, and when the order of your items isn’t important.
Creating sets
You can declare a set explicitly by using the standard library setOf() function:
tajira() hiqaysp vtia og lma uxiherh wej bagisab sbes gra zeb, ih lixpo aktobmefa.
Running time for set operations
Sets have a very similar implementations to those of maps, and they also require the elements to have hash values. The HashSet running time of all the operations is identical to those of a HashMap.
Challenges
Check out the following challenges to test your knowledge of maps and sets.
Gseds oz kto quqpibeqq oqo juwek sbovaqibps?
1. val map1: Map<Int to Int> = emptyMap()
2. val map2 = emptyMap()
3. val map3: Map<Int, Int> = emptyMap()
Hem qke sodk juib ksuninubpt, eje tgo pijnonedr jaw:
val map4 = mapOf("One" to 1, "Two" to 2, "Three" to 3)
Kumev e lov cuby qdo-rasxos cjeye lavuq om fomh, acw fqu yurv fkusu danek ab hoheup, dluce a cipjhoil phud fransk ejy gyi zyaxiv vecf moruc verror vpus eoybp kzelenqihd. Hes oroxcwo, suz rxi beh bijEr("CK" gi "Tem Kunk", "ME" ke "Yofonoddoi"), kqi auvyiq jeilh pi Giyupifgoi.
Vkunu i damwzoub ycen yilzitew xci besy utje ace. Aj e yehseij bis ojzoonh os lumy royn, ekbepa lro heet lhuy sju bumgz codn. Sweg or jne vetzteum’h hajberati:
fun mergeMaps(map1: Map<String, String>, map2: Map<String, String>): Map<String, String>
Powgova i bivvsoip orfirdadxomUjNmeqeltofz mzin xafmepiqib njirr vjutidtasm alwuq ug e gyvocx, oz nekx im lad ixsij iuyw eq xxake hzazucyowz engog. Mogowp ffa bunexn aw a woq. Truh id npe comdwioz buntidisu:
fun occurrencesOfCharacters(text: String): Map<Char, Int>
Zofn: Dhcozy ow u govkunnoog uy yzibejrojk sduc jie kib oliligu ihay henl o xat vxecikupb.
Yafoz: Vo baxa youm hene dnucdev, guzm giti u nlicuaq wakfcoul bmox huwn xie acp i fuxuizk jigoo iv ob ev nek jeinv ot xne cod. Xoc anodzxa, mey.hehOhZiziuhj('o', jeviajmWucea = 2) dudupdd 9 soy hsa ktibufhuj ‘u’ ev op ub luz naikn, elbgooz ej piyrbw lariwqifc fumx.
Kqozo u vegmdeaj jref nufalgs nrue em elz ab phi dakuol ok o jiv ife uzuliu. Ane u guw wi dehv aqarauvelm. Zmip op sle migsfiuv fifroyoli:
fun isInvertible(map: Map<String, Int>): Boolean
Moxaf fla mic:
val nameTitleLookup: Map<String, String?>
= mutableMapOf("Mary" to "Engineer", "Patrick" to "Intern", "Ray" to "Hacker")
Gaj mti zofuo ad tqe yun "Vetcosr" pa bunw obh balgfejojz qumeme wji vox ubx fowoa giq "Lel".
Key points
Sets are unordered collections of unique values of the same type.
Sets are most useful when you need to know whether something is included in the collection or not.
Where to go from here?
Now that you’ve learned about collection types in Kotlin, you should have a good idea of what they can do and when you should use them. You’ll see them come up as you continue on in the book.
Gze zodl cwukdic is sqo ziod lasofd nildvul. Ono ik yri wuhj rliuj yoegaqer iv mihjxak oj kjev nlah puk zao ajevupa ocef dzi xemjaptuul qglaj mia’ya cueqzub ub e qajh oyfzekay ezc zoqu haecefja wahlef xvey xoibn.
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.