- Idioms
- Creating DTOs (POJOs/POCOs)
- Default values for function parameters
- Filtering a list
- Checking element presence in a collection.
- String Interpolation
- Instance Checks
- Traversing a map/list of pairs
- Using ranges
- Read-only list
- Read-only map
- Accessing a map
- Lazy property
- Extension Functions
- Creating a singleton
- Instantiate an abstract class
- If not null shorthand
- If not null and else shorthand
- Executing a statement if null
- Get first item of a possibly empty collection
- Execute if not null
- Map nullable value if not null
- Return on when statement
- ‘try/catch’ expression
- ‘if’ expression
- Builder-style usage of methods that return Unit
- Single-expression functions
- Calling multiple methods on an object instance (with)
- Configuring properties of an object (apply)
- Java 7’s try with resources
- Convenient form for a generic function that requires the generic type information
- Consuming a nullable Boolean
- Swapping two variables
- TODO(): Marking code as incomplete
Idioms
A collection of random and frequently used idioms in Kotlin. If you have a favorite idiom, contribute it by sending a pull request.
Creating DTOs (POJOs/POCOs)
1. data class Customer(val name: String, val email: String)
provides a Customer class with the following functionality:
- getters (and setters in case of vars) for all properties
equals()hashCode()toString()copy()component1(),component2(), …, for all properties (see Data classes)
Default values for function parameters
1. fun foo(a: Int = 0, b: String = "") { ... }
Filtering a list
1. val positives = list.filter { x -> x > 0 }
Or alternatively, even shorter:
1. val positives = list.filter { it > 0 }
Checking element presence in a collection.
1. if ("john@example.com" in emailsList) { ... }
3. if ("jane@example.com" !in emailsList) { ... }
String Interpolation
1. println("Name $name")
Instance Checks
1. when (x) {
2. is Foo -> ...
3. is Bar -> ...
4. else -> ...
5. }
Traversing a map/list of pairs
1. for ((k, v) in map) {
2. println("$k -> $v")
3. }
k, v can be called anything.
Using ranges
1. for (i in 1..100) { ... } // closed range: includes 100
2. for (i in 1 until 100) { ... } // half-open range: does not include 100
3. for (x in 2..10 step 2) { ... }
4. for (x in 10 downTo 1) { ... }
5. if (x in 1..10) { ... }
Read-only list
1. val list = listOf("a", "b", "c")
Read-only map
1. val map = mapOf("a" to 1, "b" to 2, "c" to 3)
Accessing a map
1. println(map["key"])
2. map["key"] = value
Lazy property
1. val p: String by lazy {
2. // compute the string
3. }
Extension Functions
1. fun String.spaceToCamelCase() { ... }
3. "Convert this to camelcase".spaceToCamelCase()
Creating a singleton
1. object Resource {
2. val name = "Name"
3. }
Instantiate an abstract class
1. abstract class MyAbstractClass {
2. abstract fun doSomething()
3. abstract fun sleep()
4. }
6. fun main() {
7. val myObject = object : MyAbstractClass() {
8. override fun doSomething() {
9. // ...
10. }
12. override fun sleep() { // ...
13. }
14. }
15. myObject.doSomething()
16. }
If not null shorthand
1. val files = File("Test").listFiles()
3. println(files?.size)
If not null and else shorthand
1. val files = File("Test").listFiles()
3. println(files?.size ?: "empty")
Executing a statement if null
1. val values = ...
2. val email = values["email"] ?: throw IllegalStateException("Email is missing!")
Get first item of a possibly empty collection
1. val emails = ... // might be empty
2. val mainEmail = emails.firstOrNull() ?: ""
Execute if not null
1. val value = ...
3. value?.let {
4. ... // execute this block if not null
5. }
Map nullable value if not null
1. val value = ...
3. val mapped = value?.let { transformValue(it) } ?: defaultValue
4. // defaultValue is returned if the value or the transform result is null.
Return on when statement
1. fun transform(color: String): Int {
2. return when (color) {
3. "Red" -> 0
4. "Green" -> 1
5. "Blue" -> 2
6. else -> throw IllegalArgumentException("Invalid color param value")
7. }
8. }
‘try/catch’ expression
1. fun test() {
2. val result = try {
3. count()
4. } catch (e: ArithmeticException) {
5. throw IllegalStateException(e)
6. }
8. // Working with result
9. }
‘if’ expression
1. fun foo(param: Int) {
2. val result = if (param == 1) {
3. "one"
4. } else if (param == 2) {
5. "two"
6. } else {
7. "three"
8. }
9. }
Builder-style usage of methods that return Unit
1. fun arrayOfMinusOnes(size: Int): IntArray {
2. return IntArray(size).apply { fill(-1) }
3. }
Single-expression functions
1. fun theAnswer() = 42
This is equivalent to
1. fun theAnswer(): Int {
2. return 42
3. }
This can be effectively combined with other idioms, leading to shorter code. E.g. with the when-expression:
1. fun transform(color: String): Int = when (color) {
2. "Red" -> 0
3. "Green" -> 1
4. "Blue" -> 2
5. else -> throw IllegalArgumentException("Invalid color param value")
6. }
Calling multiple methods on an object instance (with)
1. class Turtle {
2. fun penDown()
3. fun penUp()
4. fun turn(degrees: Double)
5. fun forward(pixels: Double)
6. }
8. val myTurtle = Turtle()
9. with(myTurtle) { //draw a 100 pix square
10. penDown()
11. for (i in 1..4) {
12. forward(100.0)
13. turn(90.0)
14. }
15. penUp()
16. }
Configuring properties of an object (apply)
1. val myRectangle = Rectangle().apply {
2. length = 4
3. breadth = 5
4. color = 0xFAFAFA
5. }
This is useful for configuring properties that aren’t present in the object constructor.
Java 7’s try with resources
1. val stream = Files.newInputStream(Paths.get("/some/file.txt"))
2. stream.buffered().reader().use { reader ->
3. println(reader.readText())
4. }
Convenient form for a generic function that requires the generic type information
1. // public final class Gson {
2. // ...
3. // public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
4. // ...
6. inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)
Consuming a nullable Boolean
1. val b: Boolean? = ...
2. if (b == true) {
3. ...
4. } else {
5. // `b` is false or null
6. }
Swapping two variables
1. var a = 1
2. var b = 2
3. a = b.also { b = a }
TODO(): Marking code as incomplete
Kotlin’s standard library has a TODO() function that will always throw a NotImplementedError. Its return type is Nothing so it can be used regardless of expected type. There’s also an overload that accepts a reason parameter:
1. fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")
IntelliJ IDEA’s kotlin plugin understands the semantics of TODO() and automatically adds a code pointer in the TODO tool window.
