Start learning free

LESSON 234 OF 677 · SETS

Sets in Kotlin: HashSet, add and contains

Lesson Read the full explanation

TL ; DR:

A HashSet holds values without repeats. Adding a value that is already in it changes nothing.


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


Full lesson:

A list keeps every value you put in it, repeats too. Sometimes you only need to know which values there are. A set is made for that.

A set holds each value once. Adding a value that is already in it changes nothing.

  • hashSetOf<String>() makes an empty set of strings.
  • s.add(x) puts x in the set s.
  • s.contains(x) is true when x is in the set.
  • s.size gives how many values the set holds.
  • list.toHashSet() builds a set from a list. Its repeats go in once.

Checking s.contains(x) is fast, even for a big set. A list's contains looks at the values one by one.

Watch out for setOf(...). It makes a read-only set, so add doesn't compile on it. Use hashSetOf for a set you change.

A HashSet has no order and no indexes. A printed set may show its values in any order.


Your task

The camp's sign-up list, names, has some names twice. Build a HashSet named kids from it.

Then Zoe signs up, and Ava signs up again. Add both names to kids.

Last, if kids contains "Leo", print Leo is coming.

The code already prints the number of kids twice.

Expected output:

3 kids
4 kids
Leo is coming
STEP 1 OF 3
    Ctrl + Enter to check

    KOTLIN · SETS

    Sets in Kotlin, explained

    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) puts x in the set s. It returns true if the value was new and false if it was already there.
    • s.contains(x) is true when x is in the set.
    • s.size is 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.

    1. Build the set with names.toHashSet() in a val named kids. The list has five entries, but Ava and Leo each appear twice, so the set holds 3 names: Ava, Leo and Mia.
    2. Add "Zoe" and then "Ava". Zoe is new, so the size grows to 4. Ava is already there, so nothing changes.
    3. If kids.contains("Leo") is true, print Leo 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.
    • contains on a set is fast.
    • Use hashSetOf or mutableSetOf for a set you change; setOf is read-only.
    • Do not rely on the order a HashSet shows its values in.
    Keep going with Kotlin500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free