Kotlin Strings

Work with text in Kotlin: string templates, length and indexes, common methods like uppercase, trim and replace, substrings, splitting and multi-line raw strings.

Lesson 4 of 43Beginner17 min read

Text is everywhere in programs: names, messages, file contents, web addresses, search terms. In Kotlin, text is a String, written between double quotes.

Kotlin makes working with strings especially pleasant. Instead of gluing pieces together with +, you write string templates: put $name inside the quotes, and Kotlin inserts the variable's value. Strings also come with dozens of built-in functions to change case, trim spaces, search, replace, cut out parts and split text into lists.

In this lesson you'll build messages with templates, read individual characters, use the most common string functions, split and join text, and write multi-line text with raw strings. Strings in Kotlin are immutable: functions like uppercase() return a new string and leave the original unchanged.

String templates

Kotlin
val name = "Sam"
val items = 3
println("Hi $name, you have $items items")
println("Next year you'll be ${age + 1}")
println("Name has ${name.length} letters")
  • $name inserts a simple variable.
  • ${ ... } inserts the result of any expression, such as a calculation or a function call.
  • To print a literal dollar sign, write \$ or ${'$'}.

Templates are clearer than joining with +, and Kotlin converts numbers and other values to text automatically.

Length, characters and indexes

  • text.length is the number of characters.
  • text[0] is the first character, a Char; text[text.length - 1] or text.last() is the last.
  • Indexes start at 0, so a 5-letter word has indexes 0 to 4.
  • text.substring(0, 3) returns the characters from index 0 up to, but not including, 3.
  • text.take(3) and text.takeLast(3) give the first or last three characters, without crashing if the string is shorter.

Common string functions

FunctionExampleResult
uppercase() / lowercase()"Kotlin".uppercase()"KOTLIN"
trim()" hi ".trim()"hi"
contains(x)"kotlin".contains("tli")true
startsWith(x) / endsWith(x)"photo.png".endsWith(".png")true
replace(a, b)"a-b-c".replace("-", "/")"a/b/c"
indexOf(x)"banana".indexOf("n")2
isBlank()" ".isBlank()true
replaceFirstChar { it.uppercase() }"london""London"

Many functions take an ignoreCase = true argument, such as "KOTLIN".contains("kot", ignoreCase = true).

Splitting, joining and raw strings

split(",") turns a string into a list, and joinToString(", ") turns a list back into a string. Together they handle comma-separated values, tags and words.

A raw string uses triple quotes. It can span several lines and doesn't process escape sequences such as \n, which is handy for file paths, JSON and long messages. trimIndent() removes the indentation you added to keep the code tidy:

Kotlin
val message = """
    Dear $name,
    Your order has shipped.
""".trimIndent()

Templates still work inside raw strings.

Building strings efficiently

Strings are immutable: every + creates a new string. That's fine for a few pieces, but inside a loop that runs thousands of times it creates a lot of throwaway objects. Kotlin's buildString gives you a changeable buffer and returns the finished string:

Kotlin
val receipt = buildString {
    appendLine("Receipt")
    for ((item, price) in listOf("Tea" to 2.5, "Cake" to 3.2)) {
        appendLine("$item: £$price")
    }
    append("Thank you!")
}
println(receipt)

Inside the braces you call append and appendLine directly. For a list of values with separators, joinToString is even simpler: listOf("a", "b", "c").joinToString(", ") gives "a, b, c", and it accepts a prefix, postfix and a transform lambda.

To compare text while ignoring capital letters, use equals with a named argument: "Kotlin".equals("kotlin", ignoreCase = true) is true. Many other functions, such as contains and startsWith, accept ignoreCase = true too.

Kotlin Strings Syntax

String essentials

val s = "Hello, $name! You are ${age + 1} next year."
s.length   s[0]   s.substring(0, 5)   s.take(3)
s.uppercase()   s.trim()   s.replace("a", "b")
s.contains("x")   s.startsWith("x")   s.split(",")
listOf("a", "b").joinToString(", ")
"""multi
line""".trimIndent()
a == b   a.equals(b, ignoreCase = true)

Kotlin Strings Summary

  • Strings use double quotes; $name and ${expression} insert values into them.
  • Indexes start at 0; length, [i], substring, take and takeLast read parts.
  • uppercase, trim, contains, replace and startsWith return new strings or answers.
  • split makes a list; joinToString makes a string from a list.
  • Triple-quoted raw strings span lines; trimIndent tidies their indentation.

Kotlin Strings Examples

Each example shows the code, the output it produces and what each part does.

Example 1

Templates and string functions

Kotlin
fun main() {
    val first = "  ada "
    val last = "LOVELACE"
    val clean = first.trim().replaceFirstChar { it.uppercase() }
    val full = "$clean ${last.lowercase().replaceFirstChar { it.uppercase() }}"

    println(full)
    println("${full.length} characters")
    println(full.uppercase())
    println(full.contains("love", ignoreCase = true))
}
Output
Ada Lovelace
12 characters
ADA LOVELACE
true
Line-by-line explanation
  1. Line 4trim removes the spaces, then the first letter is capitalised.
  2. Line 5A template joins the two cleaned names with a space.
  3. Line 8${ } inserts an expression's result.
  4. Line 10ignoreCase makes "love" match "Love".
Example 2

Characters and substrings

Kotlin
fun main() {
    val code = "KT-2024-UK"
    println(code[0])
    println(code.last())
    println(code.substring(3, 7))
    println(code.take(2))
    println(code.takeLast(2))
    println(code.indexOf("UK"))
}
Output
K
K
2024
KT
UK
8
Line-by-line explanation
  1. Line 3Index 0 is the first character.
  2. Line 4last() is the final character, also a K here.
  3. Line 5Indexes 3 to 6; the end index 7 isn't included.
  4. Line 8"UK" starts at index 8.
Example 3

Splitting, joining and a raw string

Kotlin
fun main() {
    val input = "kotlin, android,  coroutines"
    val tags = input.split(",").map { it.trim() }
    println(tags)
    println(tags.joinToString(" | "))

    val user = "Sam"
    val email = """
        Hi $user,
        Your tags: ${tags.size}
        Thanks!
    """.trimIndent()
    println(email)
}
Output
[kotlin, android, coroutines]
kotlin | android | coroutines
Hi Sam,
Your tags: 3
Thanks!
Line-by-line explanation
  1. Line 3split makes a list; map with trim tidies each piece (you'll learn map in the collections lessons).
  2. Line 5joinToString joins the list with a new separator.
  3. Lines 8 to 12A raw string spans lines, templates still work, and trimIndent removes the shared indentation.

Common Kotlin Strings Mistakes

Expecting a function to change the string

Don't
val city = "london"
city.uppercase()
println(city)                // london
Do
val city = "london".uppercase()
println(city)                // LONDON

Index out of range

Don't
val word = "Hi"
println(word.substring(0, 5))    // StringIndexOutOfBoundsException
Do
println(word.take(5))            // Hi

Braces missing in a template

Don't
println("Total: $price * qty")      // Total: 4.5 * qty
Do
println("Total: ${price * qty}")    // Total: 9.0

Without braces, only the variable name is inserted; the rest is plain text.

Kotlin Strings in Real Projects

Strings in apps

Android apps build screen text with templates, clean up what users type with trim(), validate input with functions like contains("@"), and split CSV or search queries into lists. Raw strings are popular for embedding JSON in tests and SQL queries in database code, where escaping every quote would be painful.

Kotlin Strings FAQ

Are Kotlin strings mutable?

No. A String never changes after it's created; functions such as uppercase() and replace() return a new string. Assign the result, name = name.trim(), to keep it, and use buildString or StringBuilder when building text piece by piece.

What is the difference between == and === for strings?

== compares the text, so two strings with the same characters are equal. === checks whether two variables point to the very same object, which is rarely what you want for text. Use == for string comparisons in Kotlin.

How do I check whether a string is empty or blank?

isEmpty() is true for "", and isBlank() is also true for strings containing only spaces or tabs. For values that might be null, isNullOrEmpty() and isNullOrBlank() handle the null case too, which makes them handy for form input.

How do I reverse a string in Kotlin?

Call reversed(): "Hello".reversed() returns "olleH". It reverses UTF-16 characters, so text with emoji or combined accents may not reverse perfectly; for ordinary words it works as expected.

How do I remove indentation from a multi-line string?

Raw strings keep the spaces from your source code. Call trimIndent() to remove the common indentation from every line, or put a | at the start of each line and call trimMargin(), which removes everything up to and including the |.

Kotlin Strings Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the template so it prints "Hello, Ada".

val name = "Ada"
println("Hello, ")
Predict the outputeasy

What does println("Kotlin".length) print?

Predict the outputmedium

What does this print?

val s = "banana"
println(s.substring(1, 4))
Multiple choicemedium

Which line prints "Total: 15"?

Predict the outputhard

What does this print?

val parts = "a-b-c".split("-")
println(parts.joinToString(""))

Kotlin Strings Quiz

5 questions to check what you learned.

  1. What is the index of the first character in a string?

    • 1
    • 0
    • -1
    • It depends on the string
  2. What does " hi ".trim() return?

    • " hi"
    • "hi "
    • " hi "
    • "hi"
  3. What does "ABC".lowercase() do to the original string?

    • Changes it to "abc"
    • Nothing; it returns a new string "abc"
    • Deletes it
    • Throws an error
  4. What is a raw string?

    • A triple-quoted string that can span lines and doesn't process escapes like \n
    • A string without a type
    • An encrypted string
    • A string of numbers only
  5. How do you compare two strings while ignoring case?

    • a == b
    • a.compare(b)
    • a.equals(b, ignoreCase = true)
    • a === b