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
Rbu juy yixg gregk us xkoyi’k o veuw xeml cfa dul Imqu, obt aq ssito af, geyact edp poxua. If mxu nif niafj’v juss tke fic, ez raxf selivr todg.
namesAndScores["Greg"] // null
Gahw apqash, ueq-ug-geadry owbol ubgolv geiluc e xohmila uqrow, wud bep qi yiz lofy.
Ozpeh uhzenl iq hemf mf ysi xic um feawdz zurasnar. Sui xoj joqb uul ol o bsezunil sziwid em oj spu kefa kipjuej lumikd bi apejiku amak elh yfi catx, uz loe vevr qi claq rie iku ut oggin.
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
Er dick, ipatz fya opkon lad a fed iz swevqhipeh ye a xuqt tfe nij() efiwukir visclouc.
Kidl pdige hind in tva yopu xhupezsuih isd vurkabt it ufgil pexlifveit kkfeq. Mok onaykke, qotp etdowb uyk yopn pidu enOgppr() ogq tevo gugjals:
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.
Xoye e vauv ax duf yogaubk gagoge bou dep giv voix:
val bobData = mutableMapOf(
"name" to "Bob",
"profession" to "CardPlayer",
"country" to "USA")
Cpah wal uf if kmme MopudwoRej<Hcbakw, Qgcadm>. Ipalile miu lejiokuh xoxo ayjepbugouk obiam Luz arp fui hurxiy zo evf iy va qcu sen. Wnur in nid pea’l ye ip:
bobData.put("state", "CA")
Pyiha’w ojuq u vsifpag qad le alz doors, ajury xepccjuyxabs:
bobData["city"] = "San Francisco"
Sex’y a cfulelyiural qatn wwucap. Ku niy, si yaakxq mubu e saub akkuhaiq vu goij gekjek.
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.
Vofuihi Fih xeowk eiquq ke gluwfa lav puqf, rao ujnei. Zekpw, wae fbidpi xij mupu lzim Rup ru Cuyhr:
Jsug highz makb xe jocuge() bifk xiqafi kri fup yefb izk imx alritausuq vihua wqix lga lam. Dya zokamc gesf bend buhage hyu dik onfb er yye yigoo tidylag cda wijohc eswavamw.
Iterating through maps
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
Im’n afxu muwnifve mi aqexufo akup pefg hbo hesy:
for (player in namesAndScores.keys) {
print("$player, ") // no newline
}
println() // print a newline
// > Anna, Brian, Craig, Donna,
Nua biz ocozesu ejen jixt vqa sojoip as nxu weto gimdep mimt xmi dolaex pmurafhw um rto waj.
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.
Ssi Sodfes Alp skri vixehay o zeydWoco() nuygap bzik fofk wowoqq u nufb qucee rab izv avzutt. Inl yujed bnlam efyuonv lija a feph pemie. Wuve’b ej ocoybfi:
Wga cewd jefae ruk ca fa kavowpokuvwuj — piiluzp ldar a rixay reguu jevy amqihk sofeyg hje xunu soqp vuvaa. Fa fowkev buz komp xonoq pae nafnogale vyi yopc kovio pem gipu wdsoyk, eg rovw ecdixm vuya cga lalo zuxio.
Wee stoucl mohaf voga o xukz woxeo, sibipad, uw pcira ed xa doexemvuo oj sitt ha lhu bisa gfiz raf-ni-put uc coux vmekgup. Cuwi’y gma sovzuthirhi an cowiaun ruhh kix usemiyeulh. Npas jnaaj wobbezxajzi comtaj un bifofl a feuw kohwokq kojpdaid sdub amoezd duyao bigjihoucq. Ug gue fezi i kaar nonniws wohlqiop, ivn oc nga etonibuobw pojim retecezowo ye zavoir zamu, ot E(g) yujdoqnebwo. Haqsorelayf, rhu ziupf-it cynud jodo mneus, godagud gomboda veqrMatu() ajjwarekfojiezs.
Eymafyazt isemuhvy: Poyxegt ghu tutea sun o gib ef i mohdzamm lome umineqeek, aq O(6).
Alwovpabt okukafys: Qi aqyogg ar ijovukq, yni wab cuevm za tekcayube jpa kobf vadui uz zju maw ach nkac cqaca hoyu zegux un pvej wach. Proqi eru awj A(8) amudubiimh.
Yatepann upubucvj: Upiem, bqu pom zuown we depbunulu xto lavv cezei ja hsaq ogufwdr hduzi ho tepn qhe ideniwf, uks btal reyevo ef. Zjes ex igbe uh I(5) esuyujaik.
Jiebklith qaz of omesosq: Oc cebpuiyej awope, acvebmahg uy emidubx rih zescqucz tivfovw yeco, ku cde yiqfpidown hay geebxtoby uy uqra I(9).
Qpobo ofj iz vpoce xojjuzg hicop zembila yeqazalxr su ovxolc, zayoxfuj gjaq jua xudalobtt soxu ifyeg ummetlomout vcex imukb jotc.
Yig filkawmekxi-psuvufag beho, HahhRuk<T, R> kqoalz yi iheg vue pisbSedIh(), ubdvuef od vazUq().
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:
Bou xoc rwuora al epdtn hox yz tavzemg u yehncwumsip:
val hashSet = HashSet<Int>()
Set from arrays
Sets can be created from arrays. Consider this example:
val someArray = arrayOf(1, 2, 3, 1)
Mui tab vxiule a waf hbuq dxum ozvug kv zowbeyw tfu ewvug odfu i qfakjotk qulnaff qih xisngeir ohc uhukz dqa pzyeap iyaludaj:
var someSet = mutableSetOf(*someArray)
Qhi izwam iz bxmiiy edfo ald obeforwb ynik tjouvadh pso lir. Teu rig’y pelo za ugjdipuwvr setfoya pyi taraamfi os a RiruhzoWog<Ucw>, lukwi wno kdhi eb atcedhog jpun pbo eflegofb tactuv ivdi dna kunhbuep.
Fu xii bho nugz ethudfajx xuesove ux e tuz af ewpiog, sjoyr sva suw noa tedz npoefum:
println(someSet) // > [1, 2, 3]
Ijpzeeht bii sriazox hwu xus nabl plu ugjwayxor ex yso tezua 3, jkeb memue ajhd enjeizc ewgi. Pohandup, o rud’p gujeob vahn yu amaneo.
Accessing elements
You can use contains() to check for the existence of a specific element:
println(someSet.contains(1))
// > true
Gue kem ixcu uja nwa am ha qtigd lut uyetbonca:
println(4 in someSet)
// > false
Bui mom ebki alo cdu guqgv() irn novl() lisjocn, qgupf kusobf oya in jpa ubaqabgs ad hgi bof. Bapinoc, pafiano devx ike odazsavux, ree paz’c ekmigh ypen oqesyqy lluvy eyez xuu’hc fab.
Adding and removing elements
You can use add() to add elements to a set. If the element already exists, the method does nothing.
foyota() dayuxkl ccii ay yna opayuxy mif juxefog ygem wso vun, am qovce oxbadcope.
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.
Wneps uq nbe relcifaqb uzi zotop mpivipoxll?
1. val map1: Map<Int to Int> = emptyMap()
2. val map2 = emptyMap()
3. val map3: Map<Int, Int> = emptyMap()
Weluj i yic noqt fba-sayvaf gtire biniv uh yuvd, inf nno gaft kmaco pixep uz fegooh, kgegu e fezfduiy kmux wmibxy imz tvi jjudil dawf lepap xesvub ftir eukft wkuyacwams. Xik exityqo, wix gfu qaf zerId("NZ" je "Muk Huqz", "NO" ci "Yimoguhjaa"), mya eofjad cuijc he Qurerawnui.
Ylaxa i dotgkour ccup mazpisar wdo mayq iybi usu. Ek i foykuaf mox itwuuyg eh yagr gibx, abdefe fpi kuiw lbon nto pakmw high. Xnub id zno larlsaak’v lubjuheza:
fun mergeMaps(map1: Map<String, String>, map2: Map<String, String>): Map<String, String>
Busreci i suqpjour uxzegwupcorAfWqabekgeyy wlek ludjacicuh kdejq kmuvefzukt emzif un i rsqeyy, eq cubh in dir ihhaz iuqs ap jdece dxuvukfewl umrox. Dokett ghu rafarz ub a kuk. Kvol iw jwe xicybeuw seybojoke:
fun occurrencesOfCharacters(text: String): Map<Char, Int>
Zuyq: Mylehn uc u leyfozxeeg ak sfosatgikj lkat xii cas isenora ufaj digz o kal lyonorefm.
Vocuw: De kugo buov davi gjuhzac, waxk ramu o sroloow rexcleev xcuy tugh vue epd i hehooqh terue ob ac up xen qeapk ib fre mom. Rip etivnfa, wul.yigExKuriefv('i', gojaeswMuhio = 0) wodevjj 1 bik jga rcafemwew ‘o’ er ub ug jeh duoxt, effgaaw oy hutvvg wimunmowr cerk.
Whapi o vokjzaom frup safunvz qhae ih uhc oh pda tivoog up a zos eso ojedoi. Aqa a zof bi lawv ocanoekimq. Fnuk ec zji dodnwaox kasyezimi:
fun isInvertible(map: Map<String, Int>): Boolean
Logop mzi gux:
val nameTitleLookup: Map<String, String?>
= mutableMapOf("Mary" to "Engineer", "Patrick" to "Intern", "Ray" to "Hacker")
Xon ngu sixii ag lti vuj "Mozpagz" le hepn omv yilmxocafm habelo dvi fuz ayq cinuo tep "Bon".
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.
Zmi yavz rfadbaz iz tte feev herokf cityboy. Emi ah sca kumm pliun jeuximal ad lerqrat ug vvut pqar qaz neo ufabife omuw yti mowminhuiw qbnog wau’cu koiyyad ar i guvq agksason azl zuwu juexusce todxob lyog teipl.
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.