# Kotlin set

last modified August 24, 2023

In this article we show how to work with sets in Kotlin. A set is a generic unordered collection of elements which allows no duplicates.

Kotlin distinguishes between read-only and mutable sets. Read-only sets are
created with `setOf`

and mutable set with
`mutableSetOf`

.

## Kotlin setOf

The `setOf`

method creates a new read-only set in Kotlin.

package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "spectacles") println("The set contains ${words.size} elements.") }

The example creates a new set of words with `setOf`

.
The size of the set is determined with the `size`

attribute.

A set cannot contain duplicate elements.

package com.zetcode fun main() { val words2 = setOf("pen", "cup", "dog", "pen", "spectacles") words2.forEach { e -> println(e)} }

Even though we have added two pens into the `setOf`

, there will be
only one element of pen.

pen cup dog spectacles

## Kotlin Set basics

In the next example, we have a simple Kotlin Set example.

package com.zetcode fun main() { val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2) val len = nums.count() val max = nums.max() val min = nums.min() val sum = nums.sum() val avg = nums.average() val msg = """ max: $max, min: $min, count: $len, sum: $sum, average: $avg """ println(msg.trimIndent()) }

The example creates a set of numbers and computes some statistics.

val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2)

A Kotlin read-only set is created with `setOf`

function.

val len = nums.count() val max = nums.max() val min = nums.min() val sum = nums.sum() val avg = nums.average()

We compute the number of values, maximum, minimum, sum, and the average of the values.

max: 11, min: 1, count: 8, sum: 45, average: 5.625

## Kotlin Set indexing

Each element of a set has an index. Kotlin set indexes start from zero. The last
element has `len-1`

index.

package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "spectacles", "cup", "bread") val w1 = words.elementAt(0) println(w1) val i1 = words.indexOf("cup") println("The first index of cup is $i1") val i2 = words.lastIndexOf("cup") println("The last index of cup is $i2") }

The example presents Kotlin Set indexing operations.

val w1 = words.elementAt(0)

An element is retrieved with the `elementAt`

method. The method takes
an index of the element to be retrieved as a parameter.

val i1 = words.indexOf("cup")

The `indexOf`

returns the index of the first occurrence of the word
in the set.

val i2 = words.lastIndexOf("cup")

The `lastIndexOf`

returns the index of the last occurrence of the
word in the set.

pen The first index of cup is 1 The last index of cup is 1

## Kotlin Set count

The `count`

method returns the number of elements in the set.

package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val len = nums.count() println("There are $len elements") val size = nums.size println("The size of the set is $size") val n1 = nums.count { e -> e < 0 } println("There are $n1 negative values") val n2 = nums.count { e -> e % 2 == 0 } println("There are $n2 even values") }

The example returns the number of values in the set, the number of negative values and the number of even values.

val len = nums.count() println("There are $len elements") val size = nums.size println("The size of the set is $size")

We can use the `count`

method or the `size`

property to determine the number of elements in the set.

val n1 = nums.count { e -> e < 0 }

The `count`

can take a predicate function as a parameter. In our case
it returns true for values lower than 0.

val n2 = nums.count { e -> e % 2 == 0 }

We get the number of even values in the set.

There are 11 elements The size of the set is 11 There are 3 negative values There are 5 even values

## Kotlin Set first and last elements

We have methods to get the first and the last elements of the set.

package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "donkey", "spectacles") val w1 = words.first() println(w1) val w2 = words.last() println(w2) val w3 = words.findLast { w -> w.startsWith('d') } println(w3) val w4 = words.first { w -> w.startsWith('d') } println(w4) }

The example creates a set of words. We get the first and the last elements of the set.

val w1 = words.first()

We get the first element with `first`

.

val w2 = words.last()

We get the last element with `last`

.

val w3 = words.findLast { w -> w.startsWith('d') }

We retrieve the last element of the set that starts with 'd' with
`findLast`

.

val w4 = words.first { w -> w.startsWith('d') }

We retrieve the first element of the set that starts with 'd' with
`first`

.

pen spectacles donkey dog

## Kotlin Set iterate

Set iteration or Set looping is the process of going through the set elements one by one.

package com.zetcode fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "spectacles") words.forEach { e -> print("$e ") } println() for (word in words) { print("$word ") } println() for (i in 0 until words.size) { print("${words.elementAt(i)} ") } println() words.forEachIndexed({i, e -> println("$i - $e")}) val it: Iterator<String> = words.asIterable().iterator() while (it.hasNext()) { val e = it.next() print("$e ") } println() }

The example shows five ways of looping over a set in Kotlin.

words.forEach { e -> print("$e ") }

The `forEach`

performs the given action on each set element. We pass
it an anonymous function that prints the current element.

for (word in words) { print("$word ") }

We loop the set with `for`

. The `for`

loop traverses the
set element by element; in each cycle, the `word`

variable points to the next element in the set.

for (i in 0 until words.size) { print("${words.elementAt(i)} ") }

An alternative `for`

cycle utilizes the size of the set. The
`until`

keyword creates a range of the set indexes.

words.forEachIndexed({i, e -> println("$i - $e")})

With the `forEachIndexed`

method, we loop over the set
having index and value available in each iteration.

val it: Iterator<String> = words.asIterable().iterator() while (it.hasNext()) { val e = it.next() print("$e ") }

The final way is using a `Iterator`

and a `while`

loop.

pen cup dog person cement coal spectacles pen cup dog person cement coal spectacles pen cup dog person cement coal spectacles 0 - pen 1 - cup 2 - dog 3 - person 4 - cement 5 - coal 6 - spectacles pen cup dog person cement coal spectacles

## Kotlin Set sorting

The following example shows how to sort Set values in Kotlin. Since the sets
created with `setOf`

are read-only, the methods do not alter the set
but return a new modified list.

package com.zetcode data class Car(var name: String, var price: Int) fun main() { val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2) val sortAsc = nums.sorted() println(sortAsc) val sortDesc = nums.sortedDescending() println(sortDesc) val revNums = nums.reversed() println(revNums) val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val res = cars.sortedBy { car -> car.name } res.forEach { e -> println(e) } println("*************") val res2 = cars.sortedByDescending { car -> car.name } res2.forEach { e -> println(e) } }

The example sorts set values in ascending and descending order, reverses set elements, and sorts car objects by their name.

val sortAsc = nums.sorted()

The `sorted`

method returns a list of all elements sorted according
to their natural sort order.

val sortDesc = nums.sortedDescending()

The `sortedDescending`

method returns a list of all elements sorted
descending according to their natural sort order.

val revNums = nums.reversed()

The `reversed`

method returns a list with elements in reversed order.

val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600))

We create a set of car objects. These objects can be sorted by their name or by their price.

val res = cars.sortedBy { car -> car.name }

With `sortedBy`

, we sort the cars by their names in ascending
order.

val res2 = cars.sortedByDescending { car -> car.name }

With `sortedByDescending`

, we sort the cars by their names in
descending order.

[1, 2, 3, 5, 6, 8, 9, 11] [11, 9, 8, 6, 5, 3, 2, 1] [2, 6, 9, 1, 8, 3, 5, 11] Car(name=Mazda, price=6300) Car(name=Mercedes, price=18600) Car(name=Skoda, price=5670) Car(name=Toyota, price=12400) ************* Car(name=Toyota, price=12400) Car(name=Skoda, price=5670) Car(name=Mercedes, price=18600) Car(name=Mazda, price=6300)

## Kotlin Set contains

With the `contains`

method we can check if a set contains
the specified elements.

package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val r = nums.contains(4) if (r) println("The set contains 4") else println("The set does not contain 4") val r2 = nums.containsAll(setOf(1, -1)) if (r2) println("The set contains -1 and 1") else println("The set does not contain -1 and 1") }

It is possible to check if a set contains one or more elements.

val r = nums.contains(4)

Here we check if the `nums`

set contains 4. The method
returns a boolean value.

val r2 = nums.containsAll(setOf(1, -1))

This line checks if the set contains two values: 1 and -1.

The set contains 4 The set contains -1 and 1

## Kotlin mutable Set

With `mutableSetOf`

, we can create mutable sets in Kotlin.

package com.zetcode fun main() { val nums = mutableSetOf(3, 4, 5) nums.add(6) nums.add(7) nums.addAll(setOf(8, 9, 10)) println(nums) nums.remove(10) println(nums) nums.retainAll(setOf(12, 14, 16, 18)) println(nums) nums.clear() if (nums.isEmpty()) println("The set is empty") else println("The set is not epty") }

The example creates a mutable set and presents several its methods.

val nums = mutableSetOf(3, 4, 5)

We create a mutable set of three integer elements.

nums.add(6) nums.add(7) nums.addAll(setOf(8, 9, 10))

The `add`

adds a new element at the end of the set.
The `addAll`

adds multiple elements at the end of the set.

nums.clear()

The `clear`

method removes all elements from the set.

if (nums.isEmpty()) println("The set is empty") else println("The set is not epty")

With the `isEmpty`

method we check if the set is empty.

[3, 4, 5, 6, 7, 8, 9, 10] [3, 4, 5, 6, 7, 8, 9] [] The set is empty

## Kotlin Set union

The union operation returns a set containing all distinct elements from both collections.

package com.zetcode fun main() { val nums = setOf(1, 2, 3) val nums2 = setOf(3, 4, 5) val nums3 = nums.union(nums2) println(nums3) }

In the example, we have two sets of integers. We join the sets with
the `union`

method.

[1, 2, 3, 4, 5]

## Kotlin Set maximum

The following example shows how to find the maximum value of a set.

package com.zetcode data class Car(var name: String, var price: Int) fun main() { val nums = setOf(11, 5, 23, 8, 1, 9, 6, 2) println(nums.max()) val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val car = cars.maxBy { car -> car.price } println("The max price is ${car.price} of ${car.name}") }

The example finds a maximum of a set of integers and a set of car objects.

val nums = setOf(11, 5, 23, 8, 1, 9, 6, 2) println(nums.max())

The maximum of a set of integers is easily found with `max`

.

val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val car = cars.maxBy { car -> car.price } println("The max price is ${car.price} of ${car.name}")

When we deal with objects, we need to specify the attribute by which we find the
maximum. The `maxBy`

method is given a selector function that chooses
the `price`

attribute of the car.

23 The max price is 18600 of Mercedes

## Kotlin Set filter

Filtering is an opertion where only elements that meet certain criteria pass through.

package com.zetcode data class Car(var name: String, var price: Int) fun main() { val words = setOf("pen", "cup", "dog", "person", "cement", "coal", "spectacles") val words2 = words.filter { e -> e.length == 3 } words2.forEach { e -> print("$e ") } println() val words3 = words.filterNot { e -> e.length == 3 } words3.forEach { e -> print("$e ") } println() val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val res = cars.filter { car -> car.price > 10000 } res.forEach { e -> println(e) } }

The example presents the filtering operation on Kotlin sets.

val words2 = words.filter { e -> e.length == 3 }

The `filter`

method takes a predicate function as a parameter.
The predicate gives a condition that the elements must meet.
We filter out words whose length equals to 3.

val words3 = words.filterNot { e -> e.length == 3 }

The `filterNot`

does the opposite: it allows to pass through
elements that do not meet the given criteria.

val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400), Car("Skoda", 5670), Car("Mercedes", 18600)) val res = cars.filter { car -> car.price > 10000 }

These lines filter out the car objects whose price is bigger than 10000.

pen cup dog person cement coal spectacles Car(name=Toyota, price=12400) Car(name=Mercedes, price=18600)

## Kotlin Set map

The mapping operation returns a modified list by applying a transform function on each element of the set.

package com.zetcode fun main() { val nums = setOf(1, 2, 3, 4, 5, 6) val nums2 = nums.map { e -> e * 2 } println(nums2) }

We have a set of integers. With the `map`

function, we multiply each
set element by 2. The function returs a new list.

[2, 4, 6, 8, 10, 12]

## Kotlin Set reduction

Reduction is a terminal operation that aggregates set values into a
single value. The `reduce`

method applies a function against an
accumulator and each element (from left to right) to reduce it to a single
value.

package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, 7, 6, 8, 9) val sum = nums.reduce { total, next -> total + next } println(sum) }

In the example, we use the reduce operation on a set of integers.

val sum = nums.reduce { total, next -> total + next }

We calculate the sum of values. The `total`

is the accumulator,
the `next`

is the next value in the list.

45

## Kotlin Set fold

The folding operation is similar to the reduction. Folding is a terminal operation that aggregates set values into a single value. The difference is that folding starts with an initial value.

package com.zetcode fun main() { val expenses = setOf(20, 40, 80, 15, 25) val cash = 550 val res = expenses.fold(cash) {total, next -> total - next} println(res) }

We have a set of expenses. These expenses are applied on the initial amount of cash available.

val res = expenses.fold(cash) {total, next -> total - next}

With the `fold`

we deduce all the expenses from the
`cash`

and return the remaining value.

370

This is the amount that we have after subtracting all the expenses on the available amount of money.

## Kotlin Set chunked

Sometimes we need to work with more elements of a set when doing reductions. We
can use the `chunked`

method to split the set into a list of lists.

package com.zetcode fun main() { val nums = setOf(1, 2, 3, 4, 5, 6) val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] } println(res) }

In the example, we have a set of six values. We want to achieve the following
operation: `1*2 + 3*4 + 5*6`

. For this, we need to split the list
into chunks of two values.

val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] }

We split the set into a list of two-element lists and apply a fold on it. The
`next`

is a list on which we can use the indexing operations.

44

## Kotlin Set partition

The partition operation splits the original collection into pair of lists. The first list contains elements for which the specified predicate yields true, while the second list contains elements for which the predicate yields false.

package com.zetcode fun main() { val nums = setOf(4, -5, 3, 2, -1, 7, -6, 8, 9) val (nums2, nums3) = nums.partition { e -> e < 0 } println(nums2) println(nums3) }

We have a set of integers. With the `partition`

method, we split the
set into two sublists; one contains negative, the other one positive values.

val (nums2, nums3) = nums.partition { e -> e < 0 }

Using destructuring declaration, we split the set into two parts in one go.

[-5, -1, -6] [4, 3, 2, 7, 8, 9]

## Kotlin Set groupBy

The `groupBy`

method groups elements of the original set by the key
returned by the given selector function, applied to each element. It returns a
map where each group key is associated with a list of corresponding elements.

package com.zetcode fun main() { val nums = setOf(1, 2, 3, 4, 5, 6, 7, 8) val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" } println(res) val words = setOf("as", "pen", "cup", "doll", "my", "dog", "spectacles") val res2 = words.groupBy { it.length } println(res2) }

The example shows how to use the `groupBy`

method.

val nums = setOf(1, 2, 3, 4, 5, 6, 7, 8) val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" } println(res)

These lines create a map, which has two keys: "even" and "odd". The "even" points to a list of even values and the "odd" to a list of odd values.

val words = setOf("as", "pen", "cup", "doll", "my", "dog", "spectacles") val res2 = words.groupBy { it.length }

Here we create a map with integer keys. Each key groups words that have a certain length.

{odd=[1, 3, 5, 7], even=[2, 4, 6, 8]} {2=[as, my], 3=[pen, cup, dog], 4=[doll], 10=[spectacles]}

## Kotlin Set any

The `any`

method returns true if at least one element matches the
given predicate function.

package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, -1, 7, 6, 8, 9) val r = nums.any { e -> e > 10 } if (r) println("There is a value greater than ten") else println("There is no value greater than ten") val r2 = nums.any { e -> e < 0 } if (r2) println("There is a negative value") else println("There is no negative value")

The example shows the usage of `any`

.

val r2 = nums.any { e -> e < 0 }

Here we check if the set contains at least one negative value. The method returns a Boolean value.

## Kotlin Set all

The `all`

returns true if all elements satisfy the given predicate
function.

package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, -1, 7, 6, 8, 9) val nums2 = setOf(-3, -4, -2, -5, -7, -8) // testing for positive only values val r = nums.all { e -> e > 0 } if (r) println("nums set contains only positive values") else println("nums set does not contain only positive values") // testing for negative only values val r2 = nums2.all { e -> e < 0 } if (r2) println("nums2 set contains only negative values") else println("nums2 set does not contain only negative values") }

The example shows the usage of `all`

.

// testing for positive only values val r = nums.all { e -> e > 0 }

Here we test if the `nums`

set contains only positive
values.

## Kotlin Set drop

With the drop operations, we exclude some elements from the set.

package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val nums2 = nums.drop(3) println(nums2) val nums3 = nums.sorted().dropWhile { e -> e < 0 } println(nums3) val nums4 = nums.sorted().dropLastWhile { e -> e > 0 } println(nums4) }

The example shows the usage of different drop operations.

val nums2 = nums.drop(3)

With the `drop`

method, we exclude the first three elements.

val nums3 = nums.sorted().dropWhile { e -> e < 0 }

With the `dropWhile`

method, we exclude the first n
elements that satisfy the given predicate function.

val nums4 = nums.sorted().dropLastWhile { e -> e > 0 }

With the `dropLastWhile`

method, we exclude the last n
elements that satisfy the given predicate function.

[2, 1, -1, 7, 6, -8, 9, -12] [1, 2, 3, 4, 5, 6, 7, 9] [-12, -8, -1]

## Kotlin List take

The take operations are complementary to the drop operations. The take methods form a new list by picking some of the set elements.

package com.zetcode fun main() { val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12) val nums2 = nums.take(3) println(nums2) val nums3 = nums.sorted().take(3) println(nums3) val nums4 = nums.takeWhile { e -> e > 0 } println(nums4) val nums5 = nums.sortedDescending().takeWhile { e -> e > 0 } println(nums5) val nums6 = nums.takeIf { e -> e.contains(6) } println(nums6) }

The example shows the usage of various take methods.

val nums2 = nums.take(3)

The `take`

method creates a new list having the first
three elements of the original set.

val nums4 = nums.takeWhile { e -> e > 0 }

The `takeWhile`

takes the first n elements that satisfy
the predicate function.

val nums6 = nums.takeIf { e -> e.contains(6) }

The `takeIf`

methods takes all elements of the set if
the condition in the predicate function is met.

[4, 5, 3] [-12, -8, -1] [4, 5, 3, 2, 1] [9, 7, 6, 5, 4, 3, 2, 1] [4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12]

In this article we have covered Kotlin sets.

## Author

List all Kotlin tutorials.