Kotlin Collection’s appended To, By, and With

Learning Kotlin Language

Kotlin Collection’s appended To, By, and With

Understand of Collection function variants by the name

May 17 ·5min read

Picture by Jaizer Capangpangan on Unsplash

K otlin has lots of useful collection functions. It takes time to learn them all. To add to the challenge, some of the functions have variants where the name is appended with To , By and With . One good example that has it all is associate i.e. associate , associateTo , associateBy , associateByTo , associateWith and associateWithTo . :dizzy_face:

However, if we could learn what is To , By and With refers to specifically, then it will make such learning much easier.

Let’s use associate as an example, as it has the complete set as shown above.

Learning associate

To begin, let’s understand what is associate (if you already know, you could skip this section)

The official explanation is

Returns a Map containing key-value pairs provided by transform function applied to elements of the given array.

In a layman term, it is used to change a list into a map . You defined your own transformation.

data class Data(val firstName: String, val lastName: String)
val list = listOf(
Data("John", "Ali"),
Data("Naidu", "Tan"),
Data("Evgenii", "Dmitry"))
val associate = list.associate { Pair(it.firstName, it.lastName) }println(associate)
// The above line will produce a map of firstname and lastName.
// {John=Ali, Naidu=Tan, Evgenii=Dmitry}

Simple transformation. In a diagram, it looks like below.

Do note the 3 red fonts items, which will be important to describe To, By, With

  1. The Destination — where the result will be
  2. The Key Selector — determined what key should the map item based on
  3. The Value Transformer — determine how the value of the map item is formed.

In associate function, we decide everything.


The variation helpers function

1. “To” helper function to append to existing Destination

In this case, it’s associateTo

Whenever we see To , this would allow us to provide an existing destination to the function so that it could append the result to it.

val associate = list.associateTo { 
originalMap, Pair(it.firstName, it.lastName) }

This helps. Else we’ll have to do the below.

val associate = originalMap.putAll(
list.associate { Pair(it.firstName, it.lastName) })

To illustrate clearer, I provided a simple diagram below.

2. “By” helper function to determine the key selector

In this case, it’s associateBy

Whenever we see By , this basically says the function has a parameter for a lambda that help us determine the key selector

In our previous bare associate function, we has programmatically make it.firstName as the key selection.

val associate = list.associate { Pair(it.firstName, it.lastName) }

If the key selection turn out something more complicating we then would have to make a function as below

val associate = list.associate { 
Pair(getKey(it), it.lastName)) }
// the function
fun getKey(data: Data): String { return data.firstName }

In addition, if we have a complicated value transformation, we’ll have to pull it out as a function as well.

val associate = list.associate { 
Pair(getKey(it), getValue(it)) }
// the function
fun getKey(data: Data): String { return data.firstName }
fun getValue(data: Data): String { return data.lastName }

So it makes it easier, associateBy is provided, with two lambdas, one of the key, the other for the value.

val associate = list.associateBy(::getKey, ::getValue)

The diagram below illustrates that clearer

Despite associate have both Key and Value lambda, the main focus of By is to provide a way to determine the Key .

One good example is groupBy .

3. “With” helper function to determine the value result

In this case, it’s associateWith

Whenever we see With , this basically says the function has a parameter for a lambda that helps us determine the value result.

Let’s assume in our case, we just want to tie each of our elements to another value (that we could extract from the element) and form a map of “element to value”. We don’t need a new key or whatsoever, as the element will be our key.

Or course we could use associateBy as below, where the Key is just the element of the list itself

val associate = list.associateBy({it}, ::getValue)

To make it easier for us associateWith is provided.

val associate = list.associateWith(::getValue)

The diagram below illustrates that clearer

Whenever we see With , now we know that the function will have a parameter that will help determine the value result than the default one provided. Two good example is maxWith and minWith where you could determine the way you evaluate max or min .

The remaining i.e. associateByTo and associateWithTo

I don’t think I need to explain the above anymore. One look, you know what the function parameter has isn’t it? :v::+1:

Learning all other collection function variants now should be a breeze.


To — a custom destination to append your result to
By — a custom lambda to determine the key selector
With — a custom lambda to form the value result