What a set is
A list keeps every value you put in it, repeats too. Sometimes you only need to know which values there are. A set holds each value once. Adding a value that is already in it changes nothing. In Kotlin, the set you will use for this is HashSet.
val pets = hashSetOf<String>() // an empty set
pets.add("cat")
pets.add("dog")
pets.add("cat") // already in it, no change
println(pets.size) // 2
println(pets.contains("dog")) // true
The output is 2 and then true.
The basic operations
hashSetOf<String>()makes an empty set of strings.s.add(x)putsxin the sets. It returnstrueif the value was new andfalseif it was already there.s.contains(x)istruewhenxis in the set.s.sizeis the number of values in it.list.toHashSet()builds a set from a list. The repeats go in once.
Checking contains on a set stays fast even when the set is big, because it does not look at the values one by one. A list's contains does.
Other kinds of set
Kotlin has more than one way to make a set. hashSetOf gives a HashSet. mutableSetOf gives a set that can change and also remembers the order the values were added in: after mutableSetOf("pear", "apple", "fig") and adding "kiwi", then "apple" again, printing it shows [pear, apple, fig, kiwi]. The second "apple" was ignored. The in operator also works: "pear" in s means the same as s.contains("pear").
The lesson uses HashSet because the point is membership, not order.
Traps
Read-only sets. setOf("cat") makes a read-only set. Calling add on it does not compile; the compiler reports unresolved reference 'add'. Use hashSetOf (or mutableSetOf) for a set you want to change.
No order, no indexes. A HashSet has no positions, so there is no kids[0]. Printing one shows the values in an order you should not rely on. For the set in the task below, the printed set looked like this:
[Zoe, Mia, Ava, Leo]
That is not the order the names were added in. Do not write code that depends on it.
val and mutability. val kids = names.toHashSet() means kids always refers to the same set. The set itself can still grow.
The lesson's task
The camp's sign-up list names has some names twice. The task is to build a set kids from it, add Zoe and Ava, and print Leo is coming if Leo is in the set. The code already prints the number of kids twice.
- Build the set with
names.toHashSet()in avalnamedkids. The list has five entries, but Ava and Leo each appear twice, so the set holds 3 names: Ava, Leo and Mia. - Add
"Zoe"and then"Ava". Zoe is new, so the size grows to 4. Ava is already there, so nothing changes. - If
kids.contains("Leo")istrue, printLeo is coming.
class Solution {
fun mainFunction() {
val names = mutableListOf("Ava", "Leo", "Ava", "Mia", "Leo")
val kids = names.toHashSet()
println("${kids.size} kids")
kids.add("Zoe")
kids.add("Ava")
println("${kids.size} kids")
if (kids.contains("Leo")) {
println("Leo is coming")
}
}
}
It prints:
3 kids
4 kids
Leo is coming
The list names is not changed by any of this: building a set from it makes a separate collection, and names.size is still 5.
Key takeaways
- A set stores each value once; adding a repeat does nothing.
toHashSet()turns a list into a set, which is a quick way to drop repeats.containson a set is fast.- Use
hashSetOformutableSetOffor a set you change;setOfis read-only. - Do not rely on the order a
HashSetshows its values in.
