Exploring Kotlin: Useful Standard Library Functions

written by

published on

As others have written about this before Kotlin comes with a cornucopia of useful functions like let, apply, with or also. Less is written about what comes with the collections, ranges, and other packages of the standard library. In this article we'll explore them.

Tuples

Kotlin comes with Pair and Triple which are basic generic tuples:

These can be used in a lot of ways like implementing multiple return types, or destructuring but most of the time we’ll use them for Maps.

Pair comes with an useful infix function, to which lets us create one like this:

Then we can use this syntax to create Maps in a much more readable way:

Collections

If you have worked with the Kotlin stdlib for a while you probably bumped into a bunch of library functions which are either improvements over the Java versions or new additions by Kotlin. You have map, filter, reduce for example which are defined on Iterable objects and there are a bunch of others which are defined on immutable Lists, or Sets like plus or minus.

Note that from now on we’ll talk about operations which are defined for immutable collections.

Creating collections never have been easier. We have listOf, setOf, mapOf and even arrayOf to create the corresponding collection.

What’s interesting is that most of these operations are also defined for Maps.

Note that a Map in Kotlin does not implement the Collection interface, but defines some operations for Maps which are counterparts for the ones in Collection.

Maps

Kotlin treats Maps as collections of Pairs and we can create Maps from any collection which holds them:

In addition to map, filter and reduce we also have mapValues, mapKeys, filterKeys and filterValues for Maps.

mapValues and mapKeys will create new Maps when we call them. They are useful when we have a Map and we only want to transform either the keys or the values. The filter variants follow the same logic but with filtering. We can also combine them:

If we want to perform operations other than these we can turn our Map into a collection by calling toList or asIterable.

Conversions

In addition to toList, toMap and other conversion functions there are also some specialized ones which are defined on only some selected types like Byte, Boolean or Char. For example we can turn a List of Bytes to a ByteArray like this:

There is a to*Array defined for each primitive type. They all return a corresponding *Array type which is optimized.

Immutable Collections

Immutable collections are perfect for functional programming since every operation defined on them returns a new version of the old collection without changing it. This also means that they are safe from a concurrency perspective since we don’t need locks to work with them. A problem though is that we lose operations like removeAll or retainAll.

Luckily most operations which work with mutable collections have an immutable counterpart. plus and minus work like add and remove and we also have subtract, union and intersect. They work like removeAll, addAll and retainAll:

We can also work with collections in a way offset and limit works in RDBMSes. drop will return with a List without the first n elements:

dropLast works in the same way but drops elements from the end:

There is also dropWhile and dropLastWhile which drops elements until a certain condition is met:

For all of the above functions there is a take variant which works like drop but it takes elements:

These are useful but sometimes we only want to pick distinct values. We can do so by calling distinct or distinctBy. With distinctBy we can write our own selector function:

We’ve already seen ways we can turn Maps to Lists but can we do it the other way around? The answer is yes. Kotlin comes with groupBy, associate and associateBy which lets us split our Lists in different ways.

groupBy separates our List into multiple Lists grouped by keys, so the result is a multimap. We only need to provide a key selector function to do so. In this example we group a List of Ints into even and odd groups:

associate is different in a way that it transforms each element to a key-value pair and if multiple values map to the same key only the last one is returned. In our previous list of Ints which are sorted this will effectively give us the greatest odd and even numbers:

A variant to associate is associateBy which does not transform the original values but takes a key selector function. If multiple elements would have the same key only the last one is added to the resulting Map. This is an example which does the same as the previous one but with associateBy:

partition is a special transformation function which groups to only a Pair of Lists based on the result of a predicate:

We’ve seen how we can split things but let’s see what we have for joining them!

zip will work exactly like the zipper of your trousers: it zips two Lists into a List of Pairs:

We can be a bit more sophisticated if we provide a transform function to zip:

zipWithNext will pair each element with the next:

and it can also take a transform function:

Sometimes we want to transform our collections to a String representation. This is useful if we want to log the contents of them for example. For this purpose we have joinTo which takes an Appendable and some extra arguments (like a separator) and returns the Appendable with the contents of the collection appended:

Since joining to a String is so common we also have joinToString:

Honorable mentions

The examples above are far from exhaustive but there are some interesting functions which are really useful sometimes. For example we have the most commonly used String transformations as extension functions:

There are also Ranges which are very useful for iteration. We can create them directly from numbers with useful infix operations:

A real life example

These code snippets are nice but you might be wondering how a real life use case looks like. Let’s see how we can process some log information with what we have learned so far:

Conclusion

We’ve only scratched the surface with the examples above but I hope that you now have an idea about what the Kotlin stdlib has to offer. I strongly encourage you to open your IDE and take a look at these functions from the source. They are documented very well so you can get started in no time.