Collections in Kotlin

It’s time to continue our learning path in Kotlin. The subject covered in this new post is represented by Collections and data operations applied to them.

Collections are actually a set of classes and interfaces that provides high quality implementations of useful data structures and algorithms that help developers to reduce the programming effort and time.

collections kotlin magda miu

🕵️‍♀️Collections

In Kotlin there are different flavors of collections. Just like Java, all collection interfaces are originated from the Iterable interface. The main difference between Java and Kotlin is that in Kotlin we have mutable and immutable collections. An important thing to mention here is that immutable collections in Kotlin are simply read-only.

collections framework in kotlin

So in terms of collections these are the main ones:

  1. Paira tuple of two values and Triplea tuple of three values.
  2. Arrayindexed fixed-sized collection of objects and primitives.
  3. Listordered collection of objects.
  4. Setunordered collection of objects.
  5. Mapassociative dictionary or map of keys and values.

1️⃣ Pair and Triple

Very helpful if we want to quickly create two (Pair) or three objects (Triple) as a collection

🔗Pair 

📝Class definition

data class Pair<out Aout B> : Serializable

👩‍💻Code examples


// combine different data types
val testName = "Kotlin Test"
val grade = 10
val resultTest = Pair (testName, grade)
println(resultTest)
// get the parts of Pair
val book = Pair("Learn Kotlin from GDE", 20)
val (title , price) = book
println("Title = ${book.first} , Price = ${book.second}")
// infix function
val yellowScarf = "yellow" to "scarf"
println(yellowScarf.first) // => yellow
println(yellowScarf.second) // => scarf
// nesting with parentheses
val clothes = ("yellow" to "scarf") to ("blue" to "blouse")
println(clothes.second.first) // => blue

view raw

Collections.kt

hosted with ❤ by GitHub

🔗Triple

📝Class definition

data class Triple<out Aout Bout C> : Serializable

👩‍💻Code examples


// triple
var kotlinVersions = Triple(1.1, 1.2, 1.3)
var firstKotlinVersion = kotlinVersions.first
var secondKotlinVersion = kotlinVersions.second
var thirdKotlinVersion = kotlinVersions.third
// combine different data types
var kotlinBook = Triple(1289, "Learn Kotlin from GDE", 21.99)
val (isbn, title, price) = kotlinBook
println("ISBN = ${kotlinBook.first} , Title = ${kotlinBook.second} , Price = ${kotlinBook.third}")
val addressBook = Triple("Kotlin", 789456123, "Saint Petersburg")
val (name, phone, address) = addressBook
println("Name = ${addressBook.first} , Phone = ${addressBook.second} , Address = ${addressBook.third}")

view raw

Collections.kt

hosted with ❤ by GitHub

2️⃣ Array

A memory block that keeps multiple values in a sequence; very helpful for low-level optimizations.

array in kotlin

🔗Array 

📝Class definition

class Array<T>

👩‍💻Code examples


// defining arrays
val intArray = arrayOf(9, 8, 7, 6, 5, 4, 3)
val stringArray = arrayOf("one", "two", "three", "four")
val charArray = arrayOf('a', 'b', 'c', 'd', 'e')
// initialization
val ids = IntArray(5)
// defining specific arrays
var numbers = intArrayOf(1, 2, 3)
var chars = charArrayOf('a', 'b', 'c')
val programmingLanguages = arrayOf("kotlin", "java", "scala", "python")
println(programmingLanguages::class) //class kotlin.Array
println(programmingLanguages.javaClass) //class [Ljava.lang.String;
// index of the array element
println("${programmingLanguages[0]} and ${programmingLanguages[1]}") //kotlin and java
// get function
println(programmingLanguages.get(3)) //python
// size
println(programmingLanguages.size) //4
// array and for loop
for (element in stringArray) {
println(element)
}
// set function
ids[0] = 10
ids[1] = 20
ids.set(2, 30)
ids.set(3, 40)
for (element in ids) {
println(element)
}
// mutable vs immutable
val immutableArray = arrayOf(1, 2, 3)
immutableArray.set(0, 10)
immutableArray[1] = 20
// compilation error if we remove the comments from the next line
// immutableArray = arrayOf(5,6,7,8,9,10)
var mutableArray = arrayOf(1, 2, 3)
mutableArray.set(0, 10)
mutableArray[1] = 20
// arrays with different data types
val array = arrayOf(1, "hello", 'd', 19.99)
for (i in array) {
println(i)
}
println(array.contains(2))
println(array.contains('d'))
// arrayOfNulls
val nullArray = arrayOfNulls<String>(5)
nullArray.set(0, "learn")
nullArray.set(3, "kotlin")
for (element in nullArray) {
println(element)
}
/*
learn
null
null
kotlin
null*/

view raw

Collections.kt

hosted with ❤ by GitHub

Both the immutableArray and mutableArray arrays are fixed in size, but the elements of each array are mutable and can be updated. The only difference is that immutableArray is declared with the val keyword, so this array cannot be reassigned.

3️⃣ List

Data structures that hold a number of items in a sequence. Kotlin provides two different types of lists:

  • immutable lists (does not have add function)
  • mutable lists

🔗List

📝Class definition

interface List<out E> :Collection<E>

🔗MutableList

📝Class definition

interface MutableList<E> : List<E>MutableCollection<E>

👩‍💻Code examples


// immutable list and mutable list
val numbersList = listOf("one", "two", "three")
val mutableNumbersList = mutableListOf("one", "two", "three")
// alter the list using add function
mutableNumbersList.add("five")
listOf(1, 5, 3).sum() // => 9
listOf("a", "b", "cc").sumBy { it.length } // => 4
// operators
val numberList2 = numbersList + "four"
println(numberList2)
val numbersListNoTwo = numberList2 "two"
println(numbersListNoTwo)
println(numbersListNoTwo::class) //class java.util.ArrayList
println(numbersListNoTwo.javaClass) //class java.util.ArrayList
// listOfNotNull
val notNulls = listOfNotNull(32, null, "one", null, 'd')
println("Size = ${notNulls.size}")
for (element in notNulls) {
println(element)
}

view raw

Collections.kt

hosted with ❤ by GitHub

4️⃣ Set

Unordered collections of elements. Other than using setOf() / Set<T> and mutableSetOf() / MutableSet<T> we could also use hashSetOf() / java.util.HashSet<T> 

🔗Set

📝Class definition

interface Set<out E> : Collection<E>

🔗MutableSet

📝Class definition

interface MutableSet<E> : Set<E>MutableCollection<E>

👩‍💻Code examples


// immutable set and mutable set
val colors = setOf("red", "blue", "yellow", "white")
var miniColors = listOf("red", "blue")
var result = colors.containsAll(miniColors)
println(result)
val mutableColors = mutableSetOf("red", "blue", "yellow")
mutableColors.add("pink")
var mutableSetIteratorColors = mutableColors.iterator()
while (mutableSetIteratorColors.hasNext()) {
print(mutableSetIteratorColors.next())
}

view raw

Collections.kt

hosted with ❤ by GitHub

5️⃣ Map

Keeps a collection of key-value pairs.

🔗Map

📝Class definition

interface Map<Kout V>

🔗MutableMap

📝Class definition

interface MutableMap<KV> : Map<K, V>

👩‍💻Code examples


// immutable map and mutable map
val desserts = hashMapOf("whipped cream" to "cake", "chocolate" to "cookie")
println(desserts["chocolate"])
if( desserts.isNotEmpty()) {
println("desserts size is ${desserts.size}" )
}
// contains key
println(desserts.containsKey("chocolate")) //true
// contains value
println(desserts.containsValue("cake")) //true
// contains key
println(desserts.contains("chocolate")) //true
println("chocolate" in desserts) //true
val inventory = mutableMapOf("pancake" to 1)
inventory.put("cake", 3)
inventory.remove("pancake")
if( inventory.isNotEmpty()) {
println("inventory size is ${inventory.size}" )
}

view raw

Collections.kt

hosted with ❤ by GitHub

Collections vs Sequences

  • Collections are eagerly evaluated
  • Sequences are lazily evaluated
  • The difference between eager and lazy evaluation lies in when each transformation on the collection is performed.
  • In collection operation chains, each operation is applied to all elements before moving onto the next operation. In other words, one operation at a time. And it translates in creating a copy of the collection.
  • In sequence operation chains, each element receives all applicable operations before moving onto the next element. In other words, one element at a time, so no copy of the sequence (it keeps a reference to the current sequence)


var someNumbers = listOf(1, 4, 5, 6, 7, 8, 2323, 5456, 343, 2)
someNumbers
.filter { it % 2 == 0 }
.map { it * 3 }
.sum()
someNumbers
.asSequence()
.filter { it % 2 == 0 }
.map { it * 2 }
.sum()
// collection
interface Iterable<out T> {
operator fun iterator(): Iterator<T>
}
// sequence
interface Sequence<out T> {
operator fun iterator(): Iterator<T>
}
// collection
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
// sequence
public fun <T, R> Sequence<T>.map(transform: (T) -> R): Sequence<R> {
return TransformingSequence(this, transform)
}
var someNumbers = listOf(1, 4, 5, 6, 7, 8, 2323, 5456, 343, 2)
someNumbers
.filter { it % 2 == 0 } // 1 collection created
.map { it * 3 } // 1 collection created
.sum()
// total collections created = 2
someNumbers
.asSequence()
.filter { it % 2 == 0 }
.map { it * 2 }
.sum()
// total collections created = 0

Common properties and methods for collections

  • size – returns the size of your collection.
  • contains(element) – checks if the element is in your collection.
  • containsAll(elements)-checks if all elements of the collection elements are in your collection.
  • isEmpty() – shows whether the collection is empty or not.
  • joinToString() – converts the collection to a string.
  • indexOf(element) – returns the index of the first entry of the element, or -1 if the element is not in the collection.
  • clear() – removes all elements from the collection.
  • remove(element) – removes the first occurrence of an element from your collection.
  • removeAll(elements)- removes from your collection all elements contained in the collection elements.

🕵️‍♀️Data operations in a collection

📌Input data


//input data
var kotlin = Language("kotlin")
var java = Language("java")
java.town = "San Francisco"
var php = Language("php")
var scala = Language("scala")
scala.town = "New York"
var javascript = Language("javascript")
var languagesList = listOf(kotlin, java, php, scala, javascript)

view raw

Collections.kt

hosted with ❤ by GitHub

📌 Aggregate functions


// count
println(languagesList.count())
//maxBy
println(languagesList.maxBy { it.name.length })
//minBy
println(languagesList.minBy { it.name.length })
//average
println(arrayOf(8, 8, 10, 9, 9).average())
//sum
println(arrayOf(7.3, 7.6, 7.4, 7.6, 8.1, 7.7).sum())
println(languagesList.sumBy { it.releaseYear })

view raw

Collections.kt

hosted with ❤ by GitHub

📌 Search functions


//first
//NoSuchElementException could be thrown
println(languagesList.first())
println(languagesList.first { it.name.length == 3 })
println(languagesList.firstOrNull { it.name.length == 2 })
//find
println(languagesList.find { it.town.equals("San Francisco") })
println(languagesList.findLast { it.town.equals("Bucharest") })
//last
println(languagesList.last())
println(languagesList.last { it.town.contains(' ') })
//single
//IllegalArgumentException if list has more than one element
println(languagesList.single{ it.town.equals("San Francisco")})
println(languagesList.singleOrNull{ it.town.equals("Pitesti")})

view raw

Collections.kt

hosted with ❤ by GitHub

📌 Filter functions


//filter
println(languagesList.filter { it.name.contains('k') })
//filterNot(), filterNotNull()
println(languagesList.filterNot { it.name.contains('k') })
println(languagesList.filterNotNull())
//filterTo(), filterNotTo()
var listToFilterInto = mutableListOf<Language>()
languagesList.filterTo(listToFilterInto) { it.town.contains('o') }
languagesList.filterNotTo(listToFilterInto) { it.town.contains('o') }
languagesList.filterNotNullTo(listToFilterInto)
//filterIndexed()
println(languagesList.filterIndexed { index, _ -> index % 3 == 0})

view raw

Collections.kt

hosted with ❤ by GitHub

📌 Transform functions


//map
println(languagesList.map { it.town })
println(languagesList.mapIndexed { index, language -> index to language.town })
//distinct
println(languagesList.map { it.town }.distinct())
//associate(), associateBy()
println(languagesList.associate { it.name to it.town })
println(languagesList.associateBy({ it.name }, { it.company }))
//groupBy()
println(languagesList.groupBy { it.company })

view raw

Collections.kt

hosted with ❤ by GitHub

Check here my previous articles about Kotlin:

Enjoy and feel free to leave a comment if something is not clear or if you have questions. And if you like it please share!

Thank you for reading! 🙌🙏😍✌

Follow me on:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s