Operators and data types
As other programming languages, Kotlin uses + , - and *, / p. Kotlin also supports different numeric types: Int, Long, Double, Float.
There is no implicit conversion between numeric types in Kotlin.
Above statement could be checkd with following examples:
val i: Int = 6
val b1 = i.toByte()
println(b1)
val b2: Byte = 1
println(b2)
val i1: Int = b2
val i2: String = b2
val i3: Double = b2
Consider obtained results.
Change the example:
val i4: Int = b2.toInt()
println(i4)
val i5: String = b2.toString()
println(i5)
val i6: Double = b2.toDouble()
println(i6)
There are two types of variable in Kotlin: mutable and immutable. Immutable variables: with val a value could be once declared. There will be an error when trying to chnage that value.
Mutable variables: with var a value could be declared and later that value could be changed.
Condier following example:
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
Working with strings in Kotlin is similar to other programming languages. “ - is used for strings, ‘ - is used for chars, + - concatenation, $ - pattern creation, {} - used for pattern expressions.
Example:
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
"I have ${numberOfFish + numberOfPlants} fish and plants"
Comparison
Similar to other languages, Kotlin supports boolean operators like less than, equal to, greater than, etc. (.<==>!=<=>=)
Example:
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
println("Good ratio!")
} else {
println("Unhealthy ratio")
}
Range expression
val fish = 50
if (fish in 1..100) {
println(fish)
}
Nested conditions
if (numberOfFish == 0) {
println("Empty tank")
} else if (numberOfFish < 40) {
println("Got fish!")
} else {
println("That's a lot of fish!")
}
Conditional statement:
when (numberOfFish) {
0 -> println("Empty tank")
in 1..39 -> println("Got fish!")
else -> println("That's a lot of fish!")
}
Nullable
Varibles in Kotlin cannot be null by default.
Try following code line:
var rocks: Int = null
In order to define that variable could be null, quotation mark should be used after the data type.
var marbles: Int? = null
Example:
var fishFoodTreats = 6
if (fishFoodTreats != null) {
fishFoodTreats = fishFoodTreats.dec()
}
Operator (?:) - takes the right-hand value if the left-hand value is null.
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
fishFoodTreats = fishFoodTreats?.dec() ?: 0
Operator !! - asserts that an expression is non-nullable.
val len = s!!.length
Collections
List definition with listOf:
val school = listOf("mackerel", "trout", "halibut")
println(school)
List definition with mutableListOf:
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
Array definition with arrayOf, intArrayOf:
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
val mix = arrayOf("fish", 2)
val numbers = intArrayOf(1,2,3)
Operator +
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
Try different combinations of nested arrays ans lists. As in other programming languages, arrya elements could be lists and viceversa.
val numbers = intArrayOf(1, 2, 3)
val oceans = listOf("Atlantic", "Pacific")
val oddList = listOf(numbers, oceans, "salmon")
println(oddList)
Arrays initialization:
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
Array iterations
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
print(element + " ")
}
for ((index, element) in school.withIndex()) {
println("Item at $index is $element\n")
}
for (i in 1..5) print(i)
for (i in 5 downTo 1) print(i)
for (i in 3..6 step 2) print(i)
for (i in 'd'..'g') print (i)
var bubbles = 0
while (bubbles < 50) {
bubbles++
}
println("$bubbles bubbles in the water\n")
do {
bubbles--
} while (bubbles > 50)
println("$bubbles bubbles in the water\n")
repeat(2) {
println("A fish is swimming")
}
Functions
fun main(args: Array<String>) {
println("Hello, world!")
}
fun printHello() {
println ("Hello World")
}
printHello()
Parameter passing in main method
fun main(args: Array<String>) {
println("Hello, ${args[0]}")
}
Examples:
fun feedTheFish() {
val day = randomDay()
val food = "pellets"
println ("Today is $day and the fish eat $food")
}
fun main(args: Array<String>) {
feedTheFish()
}
fun randomDay() : String {
val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday", "Sunday")
return week[Random().nextInt(week.size)]
}
fun fishFood (day : String) : String {
var food = ""
when (day) {
"Monday" -> food = "flakes"
"Tuesday" -> food = "pellets"
"Wednesday" -> food = "redworms"
"Thursday" -> food = "granules"
"Friday" -> food = "mosquitoes"
"Saturday" -> food = "lettuce"
"Sunday" -> food = "plankton"
}
return food
}
fun feedTheFish() {
val day = randomDay()
val food = fishFood(day)
println ("Today is $day and the fish eat $food")
}
fun fishFood (day : String) : String {
val food : String
when (day) {
"Monday" -> food = "flakes"
"Wednesday" -> food = "redworms"
"Thursday" -> food = "granules"
"Friday" -> food = "mosquitoes"
"Sunday" -> food = "plankton"
else -> food = "nothing"
}
return food
}
fun fishFood (day : String) : String {
return when (day) {
"Monday" -> "flakes"
"Wednesday" -> "redworms"
"Thursday" -> "granules"
"Friday" -> "mosquitoes"
"Sunday" -> "plankton"
else -> "nothing"
}
}
Default values
fun swim(speed: String = "fast") {
println("swimming $speed")
}
Required parameters
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
return when {
temperature > 30 -> true
dirty > 30 -> true
day == "Sunday" -> true
else -> false
}
}
fun feedTheFish() {
val day = randomDay()
val food = fishFood(day)
println ("Today is $day and the fish eat $food")
println("Change water: ${shouldChangeWater(day)}")
}
Compact functions
fun isTooHot(temperature: Int) = temperature > 30
fun isDirty(dirty: Int) = dirty > 30
fun isSunday(day: String) = day == "Sunday"
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
return when {
isTooHot(temperature) -> true
isDirty(dirty) -> true
isSunday(day) -> true
else -> false
}
}
Filters
Filters are an easy way to get a part of list based on some condition (or state).
Let’s define collection:
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
How to print symbols with ‘p’
Eager and lazy filters
By default, filters are eager meaning every time a collection is created when filter is used.
fun main() {
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
// eager, creates a new list
val eager = decorations.filter { it [0] == 'p' }
println("eager: $eager")
}
In order to have a lazy filter, asSequence should be used for definition:
val filtered = decorations.asSequence().filter { it[0] == 'p' }
println("filtered: $filtered")
val newList = filtered.toList()
println("new list: $newList")
Element transformers
Example 1:
val lazyMap = decorations.asSequence().map {
println("access: $it")
it
}
println("lazy: $lazyMap")
println("-----")
println("first: ${lazyMap.first()}")
println("-----")
println("all: ${lazyMap.toList()}")
Example 2:
val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
println("access: $it")
it
}
println("-----")
println("filtered: ${lazyMap2.toList()}")
Lambda expressions
In addition to traditional functions, Kotlin supports lambdas. A lambda is an expression that performs a function, but instead of declaring a named function, unnamed function is declared. The lambda expression can be passed as data. In other programming languages, lambdas are called anonymous functions, function literals, or similar names.
Example:
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
Lambda definition:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
In example above, variable waterFilter is created. This variable could be any function with int input and output. Lambda function is assigned to that variable, returning argument value divided by dirty/2.
Functions with Lambda parameter
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
return operation(dirty)
}
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
Named function passed
fun increaseDirty( start: Int ) = start + 1
println(updateDirty(15, ::increaseDirty))
Example
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)