Advanced Functions
Filter
filter(){} does the filtering. Filtering is one of the most popular tasks in collection processing. Filter is a condition element. These functions leave the original collection unchanged, so they are available for both mutable and read-only collections.
fun main(args: Array) {
val list = listOf(1,4,6,7,9)
val selectedList = list.filter { number -> number < 5 } // {it<5}
for(number in selectedList){
println(number)
}
}
Output:
1
4
MAP
Unlike filter, map changes the values of the list.
fun main(args: Array) {
val list = listOf(1,2,4,5,7,8,9)
val mapList = list.map { it+it }
for (map in mapList){
println(map)
}
}
Output:
2
4
8
10
14
16
18
filter and map combination
Filter and Map can be used together.
fun main(args: Array) {
val person = listOf(
People("Attila Hun",23,"Male"),
People("Khaleesi the queen <3",24,"Female"),
People("Homelander",33,"Transgender"),
People("Sauron",323,"Genderqueer"),
People("Galadriel",250,"Cisgender"),
People("Gandalf",273,"Genderfluid")
)
val listCombine = person.filter{pers -> pers.age> 240}
.map { perso -> perso.gender }
for(i in listCombine){
println(i)
}
}
data class People(val name: String, val age: Int, val gender: String)
Output:
Genderqueer
Cisgender
Genderfluid
let
"let" takes the object it is invoked upon as the parameter and returns the result of the lambda expression. Kotlin let is a scoping function wherein the variables declared inside the expression cannot be used outside. let is usually used for nullable types.
private var numb: Int? = null
fun main(args: Array) {
numb?.let {
val numb2 =it+1 //using val over var is preferable because the variable defined cannot be used outside the scope of let. Using val is more correct in terms of its structure.
println(numb2)
}
}
Output:
//Empty
sample II
private var numb: Int? = 8
fun main(args: Array) {
numb?.let {
val numb2 =it+1
println(numb2)
}
}
Output:
9
sample III
It would be good to put a question mark before the .let, otherwise it may be necessary to use it in the steps inside. Since ". let" is a method based on working with null, it is better to put the question mark at the beginning.
private var numb: Int? = 8
fun main(args: Array) {
val num = numb?.let { value ->
value + 1
}
println(num)
}
Output:
9
- Lambda usage is shown in the above code.
let and null value
private var numb: Int? = null
fun main(args: Array) {
val num = numb?.let { value ->
value + 1
} ?:0
println(num)
}
Output:
0
also
With "also", things to do can be placed between the corresponding bracket. Multiple operations can be performed in a single line.
fun main(args: Array) {
val ati = Person("Ati",31)
val leo = Person("Leo",64)
val shiv = Person("Shiv",21)
val people = listOf(ati,leo,shiv)
people.filter { it.age>28 }.also {
for (per in it){
println(per.name)
}
}
}
data class Person (var name:String, var age:Int)
Output:
Ati
Leo
apply
Kotlin apply is an extension function on a type. It runs on the object reference (receiver) into the expression and returns the object reference on completion.
fun main(args: Array) {
val person = Person("ati",24)
person.apply { this.age = 13 }
println(person)
}
data class Person(var name: String, var age : Int)
Output:
Person(name=ati, age=13)
apply and also
apply and also can be used together.
fun main(args: Array) {
Person("ari",12).apply {
name = "ARI"
}.also {
println(it.name)
}
}
data class Person(var name: String, var age : Int)
Output:
ARI
apply sample II
fun main(args: Array) {
val person = Person("ari",12).apply {
name = "ARI"
}
println(person.name)
}
data class Person(var name: String, var age : Int)
Output:
ARI
run
Run method is very important for nullable safety.
class ClassRoom(){
lateinit var names: String
lateinit var teachers: String
lateinit var schools: String
}
fun main(){
println("ClassRoom name: ")
var classRoom: ClassRoom? = null
classRoom?.run {
print(names) //Not print on the screen cause object is null.
}
print("ClassRoom name: ")
classRoom = ClassRoom().apply {
names = "Merve Grealish"
teachers = "Mete Cengiz namıtürk"
schools = "Atatürk University"
}
classRoom.run { //successful.
print(names)
}
}
Output:
ClassRoom name:
ClassRoom name: Merve Grealish
When the classRoom value is null, the body of the run is simply ignored. When it is non-null, the body executes.
with
The class/object is put inside the with function. Since this function returns unit type it might be better to put the variable.
fun main(args: Array) {
val pers = with(Person("Ari",13)){
name = "ARI"
}
println(pers.name) // unit type x. no return.
}
data class Person(var name: String, var age : Int)
Output:
//unit type
sample II
fun main(args: Array) {
val pers = Person("Ari",13)
with(pers){
name = "ARI"
age = 43
}
println(pers.name + " " + pers.age)
}
data class Person(var name: String, var age : Int)
Output:
ARI 43
Summary
Function selection
Function | Object reference | Return value | Is extension function |
---|---|---|---|
let | it | Lambda Result | Yes |
run | this | Lambda Result | Yes |
run | - | Lambda Result | No: called without the context object |
with | this | Lambda Result | No: takes the context object as an argument. |
apply | this | Context object | Yes |
also | it | Context object | Yes |
-> Some good resources on the subject: