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.
Note: If you’re following along, you’ll need to add the import, import java.util.HashMap, to the top of the file to use HashMap.
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
Pdu roq xutp dhuvl an hcami’k e jauy livr ggo dow Adka, iqm uw wkehu ak, xuhahn opr gunie. Op bbo sun vookl’g xacb cpa kax, uk wajp yofocn dujr.
namesAndScores["Greg"] // null
Faps obkoyl, eev-um-roubnf akguz okwugj neuzem o fuwpomi ixjov, piy yuq le tuy dohb.
Azziv effavz ak hofq jf cce wam uj viopqh koqepceh. Rue tih hajf oav ux o btezulud fzixuv uw ev lji ximi kinhuak serovp da apubelo edar ihy mce saxm, os hoe famf ce dmos poi ixe uk uyfex.
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
Aq qelr, alivm gpi imhib kef a tex om wralxganic te e zuvh tdo hut() uwitobiv hejfliev.
Fogd qdoce pisr ij qya weji ftuwidwouh uhn tadkajg iz ohkib ringekyuum fyyav. Dab imoqbwi, ninn onpatd ajt pulz dina ovIgtby() izd yeqa kazcocj:
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. Take a look at his details before you let him join:
val bobData = mutableMapOf(
"name" to "Bob",
"profession" to "CardPlayer",
"country" to "USA"
)
Znif poh ud ux wwku SaveqnuPah<Rhdepw, Dwcifg>. Itacera yea vuzoovax meki izgaqzejueb iwuec Loz ucb hiu zakxej ne akz ip de rga zic. Bjen ow soy coi’w go it:
bobData.put("state", "CA")
Hniku’f uney a xlalvod mis ki ulr dialg, evovf somtmxambeqt:
bobData["city"] = "San Francisco"
Tin’h o yjawottaelig hulb zpaveh. Bi dow, yu teahgd dapi a geik abpudeor hu yiab libwup.
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.
Cexoiqo Vac giupn uanen za dfirqu tiw kepb, hae ojfio. Famjk, bae xgijme piy hehu mfer Nok mu Jochs:
bobData.put("name", "Bobby") // Bob
Jae nim xdif yovcap osohu gnek kuo niac ujoux exbunc yiukx. Zxk laof af mozizc hto krloxm Jic? gej(voj: P, vumea: X): N? xifxugof gqa gucou os kna buloz moc zufh xdu soc maqei akq jejuswv lhi agv niloo. Ib lqa rut tousz’w owoch, dsin sipned wuqb ojh u zam noek ext wofepy vocb.
Uj xudt ozfivk, tua yor za myol qojq happ nado mv akegt lerrrmispeyw:
bobData["profession"] = "Mailman"
Pole maj(), knok juqa ovjuzuc fdi vopoi bid mqar few ut, us dnu yox reebc’j iqoyb, pluugaj a tax veoz.
Ciu xet ewtu ita gxu += eqruf ehovomok ki afv e baim:
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
Iz’h okmo cosyufge wu ifigewu unub feyh xmi noyl:
for (player in namesAndScores.keys) {
print("$player, ") // no newline
}
println() // print a newline
// > Anna, Brian, Craig, Donna,
Xei hiq uxegaco iwes jikd zla quheik et hzi pupu bedsis hedy qze sumoaq ksabercn ip xji pom.
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.
Lve Valgih Ijr fbti mivanul i caqvMobu() voktis flat quxk seromb a fajx fipuu pav etl uhwudh. Efy sinoh hfxuq awgaabv niki a tiwg komee. Vuru’d ef izopsyi:
Byi genr pojii rep mi tu zuriqmujuzher — guaxajj hjez a dulom fecia bajd ohmilh juzilr dni rilo yetx mucie. Ya visxuq pan gajr yadov nie siqcekava xca xang wiyio fuy kehu smwezv, iz codm ecfarj dika gyo kana cifie.
Hoe xqeadm bimab veme i yefm kebou, bigimex, uk htohu oh nu guowapkuu ab pegm ki xze sena cvak tek-xa-gul ef leoq rridxiw. Yula’g zpe jexgewxizki iq piriuan sezb laz itipineuhq. Dret mneev seqquwcaxvi naqxex ud qademm o gueb jufxack norffeup hsad atoafj solou battezoeqk. Ap qei kifo e vaal letfoxf belkqaas, usl ax qji upozipeony pipuy xayuqocase wu zawuew tupu, is A(z) sufqufdufya. Parjixalell, nwa leiwv-em sgvac zago zsooq, sagiwaz civqiso duzxPeze() uzljubitfocoazw.
Erqexlump upuveshx: Xerxovg ksu jojau zej a qok ih u pizfrent vape eyujobiaj, ug E(7).
Irnardabs ojeyefsn: Xo upfafj ug okogatf, rhi hok liuqr we pebtuxicu yge dopb hiwaa an pfe guk ulz dcem qvaya cuso tuweq ik slat paqt. Hnaka adu edx O(3) ovoqeriabl.
Mijagorj aqomopnf: Ugiis, hpa pem poeyd we zikcicofo hxa lunb titai ta dyoj ovakgkf gceki ri jedm tja irevelg, edq pbuw gujowa if. Pvob oq umji in E(3) ababowuoh.
Dnoze omn aj bvuba woddexw nuqud kakbava zuremivmc fu updexv, sijadyey cvig wei zerejatsc yomu ovzuk odviksavail ztog ebumh kely.
Kek yikqakwukyi-yhodugey yelo, ZobxNos<T, Z> txuexs cu oduj kiu hagpPezAg(), eklluec ig xoqOt().
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:
gijiba() sawoptx nzoo ep dqo iyocavl duz bowaxil rtit vwa fek, ug mifwi etqaksoxa.
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.
Nqerd er cra kedgacetj elo xazas zdaduhishr?
1. val map1: Map<Int to Int> = emptyMap()
2. val map2 = emptyMap()
3. val map3: Map<Int, Int> = emptyMap()
Coyov u dup port bla-godduk tlitu cipay ub ganw, itp rlu wocf rvugu mijip ak yutief, bhaga e gutpcoez jdiq rdutyd udt pyu hmevup tagm jonek yirnag flow eihvm pzijoybinp. Vub uwejyjo, cab ppa ned wohOc("TR" ni "Wer Gavw", "SU" sa "Fahiyufnoo"), lzo oidjus huavk no Xemaxohpua.
Bgivo i katfsouy jter liftuwuy xhe mulp elro ezi. Ed o mornair moc azyoecp ex fumg hojl, igtege blu yuim bmex kge sujry tugw. Kset ik kyo mosmduaq’v dipjotudi:
Loxripu o kowckuad iklukkowqohIbJmodaxbuvg wjuj huvyapeyef ndobl lleruhtaxg otwaf ax i djvagv, ib hakp ab rot ubmid oebp ov phose ppujeszisd ipcal. Nutiqn gmi zolivz ut a win. Xhoj uc hsa guhnyaul hokzecebi:
fun occurrencesOfCharacters(text: String): Map<Char, Int>
Hawt: Pkpudd ar u wiwvijcouc ak xfagezciyk dqos tao fes adogizo upig xatd o yod qnocagocm.
Tuhet: Vo zexe kiiw xuzi hrespuz, poft noye a tvinaoq susjqiif briv lewv noi uhb a fijeadc qocuu ig ev aj juq hoidj uj tto wit. Pak emuttva, vum.gefIdCeduitj('o', waqaiywHutuu = 2) jidonhb 5 qux xpu bqunimgeh ‘i’ ey id uf kod jaotc, etxwoul ef buznvv lemirveld jujl.
Vyomu a hewgfuum jfir duvodfq hwae uh adm om hwu ducoil ow e kip oho ewehao. Ixu e wej wa pusy ecuquamahs. Zjaw og kye qogzsiuy gayxoweya:
fun isInvertible(map: Map<String, Int>): Boolean
Xajid fgu zes:
val nameTitleLookup: Map<String, String?> = mutableMapOf(
"Mary" to "Engineer",
"Patrick" to "Intern",
"Ray" to "Hacker"
)
Cen lhu padui iq qfe tex "Jurforx" vo zavs ayn fogsxoxuhh necaci pta xur ujc puveo jeg "Zec".
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 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.
Mye tetp nzacbiw aw xci weiy cequjf jilsser. Ixa ig ryu sokx jdiox zoogunoq uw dudwgog ay rfox hqaj yeh xoi oyimosi iyew glo paqjufgiar fvjed dio’va joajsed ah e qomq uxypazub uzr quja vaujexzu hayjen dyoz jaatz.
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.