Kotlin: How to use .filter( ), ‘it’ key word, and arrow ‘->’ operator

Kotlin’s built-in .filter() function is meant to iterate through any iterable collection type, (lists, sets, or maps) and check each element of the collection against some criteria (aka “predicate”). If the element matches the predicate, meaning the boolean result is true, then the element is added to a result collection of the same type that is being checked.

For example, if checking a list of strings for any string that is not empty, every string that is not empty will be placed in a result list.

If checking a map of names and phone numbers for valid phone numbers, where names are keys and phone numbers are values, then every valid name / phone number combination will be added to a result map.

Here is what kotlinlang.org says about filter():

In Kotlin, filtering conditions are defined by predicates – lambda functions that take a collection element and return a boolean value: true means that the given element matches the predicate, false means the opposite.

The basic filtering function is filter(). When called with a predicate, filter() returns the collection elements that match it. For both List and Set, the resulting collection is a List, for Map it’s a Map as well.

The syntax for using .filter on a collection is:

collection.filter { predicate }

Where “predictate” is a boolean check that is run on each item in the collection.

Note:
What is odd about this syntax is that where we would expect to see parenthesis used, as in .filter(), curly braces are used instead. i.e. .filter { }. This is because Kotlin allows the parenthesis to be left off when defining as function in line. The parenthesis indicate the beginning and end of the lambda function definition. This syntax also works: .filter() { }

Example 1: Using .filter on a list (or set) collection

Here is an example of running filter on a list (or set):

val numbers = listOf("one", "two", "three", "four")  
val longerThan3 = numbers.filter { it.length > 3 }
println(longerThan3)

// or

val numberOne = numbers.filter { it == "one" }
println(numberOne)

Which yields:

[three, four]
or
[one]

Here the collection is a list of strings called “numbers”.
The predicate is a check of the length of each string.

numbers.filter { it.length > 3 }

The it keyword is the name that Kotlin gives to the next single parameter in a collection as it is iterated on by a lambda function such as .filter.

The output is another list called “longerThan3”, which will contain a list of all of the elements of the collection that passed the predicate check with a boolean value of true.

Example 2: Using .filter on a map collection

Here is an example of running filter on a map, which is a collection of key – value pairs.

val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10}
println(filteredMap)

Since a map is a collection of key / value pairs we use (key, value) in place of it on the parameter side, we use arrow -> notation on the left side of the predicate. For example:

.filter { (key, value) ->

And since we have key and value in map collections, we can use either key or value or both in the predicate. For example:

key.endsWith("1") && value > 10}

The above example of using .filter on a map collection yields:

{key11=11}

Here is what the Kotlin documentation says about the arrow -> operator:

separates the parameters and body of a lambda expression

separates the parameters and return type declaration in a function type

separates the condition and body of a when expression branch

For more details about .filter(), see:
https://kotlinlang.org/docs/reference/collection-filtering.html#filtering

For more information about the it key word, go here.

For more information about the -> operator, see:
https://kotlinlang.org/docs/reference/keyword-reference.html