Kotlin
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Null Safety
-
Section 4: Object-Oriented Kotlin
-
Section 5: Functional Kotlin
-
Section 6: Coroutines
-
Section 7: Collections Deep Dive
-
Section 8: Type System Deep Dive
-
Section 9: Interop and Tooling
-
Section 10: Kotlin DSLs and Patterns
-
Section 11: Testing and Quality
-
Section 12: Server-Side Kotlin
-
Section 13: Practical Projects
-
Section 14: Interview Practice
-
Section 15: More Practice Exercises
-
Section 16: More Standard Library
-
Section 17: Multiplatform Kotlin
-
Section 18: kotlin.collections In Depth
-
Section 19: kotlin.text In Depth
-
Section 20: kotlin.ranges and kotlin.sequences
-
Section 21: kotlin.io and File Handling
-
Section 22: kotlinx.coroutines Deep Dive
-
Section 23: kotlin.reflect
-
Section 24: Android Development with Kotlin Overview
-
Section 25: Kotlin Multiplatform Deep Dive
-
Section 26: Kotlin for Backend Deep Dive
-
Section 27: Kotlin Design Patterns
-
Section 28: Advanced Language Features
-
Section 29: More Practice Exercises
-
Section 30: More Interview Practice
-
Section 31: Kotlin Type System Deep Dive
-
Section 32: Kotlin Null Safety Advanced
-
Section 33: Kotlin Testing Deep Dive
-
Section 34: Kotlin Build Tooling Deep Dive
-
Section 35: Kotlin Serialization
-
Section 36: Kotlin Performance Considerations
-
Section 37: Kotlin Native Overview
-
Section 38: Kotlin for Data and Scripting
-
Section 39: More Coroutines Practice
-
Section 40: More Android-Adjacent Patterns
-
Section 41: More Practical Projects
-
Section 42: More Design and Architecture Practice
-
Section 43: Kotlin Language Evolution
-
Section 44: More Interview and Review
-
Section 45: Kotlin Delegation Patterns Deep Dive
-
Section 46: Kotlin Annotations Deep Dive
-
Section 47: Kotlin for Gradle Plugin Development
-
Section 48: Kotlin Concurrency Beyond Coroutines
-
Section 49: Kotlin Compiler Internals
-
Section 50: Real-World Kotlin Case Studies
-
Section 51: Final Practice Projects
-
Section 52: Kotlin for Server-Side Reactive Programming
-
Section 53: More Practice and Drills
-
Section 54: Kotlin Security Practices
75: Working with Strings in Kotlin
I once worked with a developer who spent an entire afternoon debugging a CSV export tool. He was using the old-school Java approach of concatenating strings with the + operator, manually adding commas and quotes. He missed one single space in a complex conditional block, and it shifted every column in the resulting file by one position. By the time he found the typo, he was exhausted. It was a classic case of "string fatigue"—where the logic of your program gets buried under a mountain of quotation marks and plus signs.
In Kotlin, we avoid that fatigue by treating strings as more than just arrays of characters. They are first-class citizens with a wealth of built-in power that makes your code read like a sentence rather than a puzzle.
Beyond Concatenation with String Templates
You'll quickly find that you almost never need the + operator for strings in Kotlin. Instead, we use string templates. If you have a variable, you just prefix it with a dollar sign. If you need to perform a calculation or call a function inside the string, you wrap it in curly braces. It's a small shift, but it keeps your business logic visible and your formatting clean.
val user = "Alex"
val attemptCount = 3
val message = "Hello, $user! You have ${attemptCount * 2} attempts remaining."
// Output: Hello, Alex! You have 6 attempts remaining.
I always tell people to lean into the curly braces even when they aren't strictly necessary for complex expressions; it makes the template a bit more explicit and easier to scan when you're reading a 50-line file.
Handling Multi-line Blobs with Raw Strings
If you've ever had to write a SQL query or a JSON snippet inside a string, you know the pain of escaping double quotes and adding \n everywhere. Kotlin solves this with raw strings, denoted by triple quotes ("""). These strings ignore escape characters, meaning you can literally hit Enter and start a new line in your code, and that newline will be preserved in the string.
The one catch is that raw strings preserve all the leading whitespace used for indentation in your source code. To fix this, we use .trimIndent(). This function looks for the common minimal indent of all the lines and strips it away, allowing you to keep your code aligned without adding unwanted tabs to your actual output.
val jsonResponse = """
{
"status": "success",
"data": {
"id": 101,
"name": "Kotlin Course"
}
}
""".trimIndent()
Slicing and Dicing with String Utilities
The Kotlin standard library provides a set of utilities that I use daily to avoid writing tedious for loops or complex regex. For instance, substringBefore() and substringAfter() are absolute lifesavers when parsing simple delimited data. Instead of finding the index of a character and then adding one to it to slice the string, you just tell Kotlin what the delimiter is.
Another common point of confusion I see is the difference between isEmpty() and isBlank(). An empty string has a length of zero. A blank string might contain five spaces, but it has no "meaningful" content. If you're validating user input, you almost always want isBlank(), because a user entering three spaces shouldn't count as a valid username.
val logEntry = "ERROR [2023-10-12]: Connection timeout"
val timestamp = logEntry.substringAfter("[").substringBefore("]")
val message = logEntry.substringAfter(": ")
println(timestamp) // 2023-10-12
println(message) // Connection timeout📋 Practical Task
Exercise: Building a Custom Transaction Log Parser
You have been handed a raw string containing a batch of financial transactions. Your goal is to parse this raw blob and print a human-readable summary for each transaction using the string techniques covered in this lesson.
Requirements:
- Store the raw data in a multi-line raw string (using
""") and use.trimIndent()to clean it up. - Split the raw string into individual lines.
- For each line, extract the ID, the Amount, and the Currency. (Assume the format is
ID:123 | AMT:45.50 | CUR:USD). - Print a final formatted string for each transaction like this:
"Transaction 123 was processed for 45.50 USD"using string templates.
val rawData = """
ID:TXN001 | AMT:120.00 | CUR:USD
ID:TXN002 | AMT:45.50 | CUR:EUR
ID:TXN003 | AMT:300.10 | CUR:GBP
""".trimIndent()
// Your parsing logic here
There are no comments for now.