Chuỗi ký tự (String) trong Kotlin
🎯 Mục tiêu: Thành thạo làm việc với String trong Kotlin - từ cơ bản đến các kỹ thuật nâng cao như multi-line strings và string manipulation.
💡 Khái niệm
String là chuỗi các ký tự được bao bọc bởi dấu nháy kép "...". Trong Kotlin, String là immutable (không thể thay đổi sau khi tạo).
val greeting = "Xin chào, Kotlin!"
val empty = ""
val unicode = "こんにちは 🎉"📝 Tạo String
String thông thường (Escaped strings)
val name = "Bumbii"
val path = "C:\\Users\\Bumbii" // Cần escape backslash
val quote = "Anh ấy nói: \"Hi!\"" // Cần escape dấu nháyRaw String (Multi-line strings)
Dùng """...""" (triple quotes) cho chuỗi nhiều dòng mà không cần escape:
val json = """
{
"name": "Bumbii",
"age": 25,
"city": "Hanoi"
}
""".trimIndent()
val html = """
<html>
<body>
<h1>Hello Kotlin</h1>
</body>
</html>
""".trimIndent()[!TIP] Luôn dùng
.trimIndent()hoặc.trimMargin()để loại bỏ khoảng trắng thừa.
trimMargin với custom delimiter
val text = """
|Line 1
|Line 2
|Line 3
""".trimMargin()
// Hoặc dùng delimiter khác
val custom = """
>First line
>Second line
""".trimMargin(">")🔍 String Templates (Quan trọng!)
Kotlin hỗ trợ String interpolation built-in:
val name = "Bumbii"
val age = 25
// Đơn giản: $variable
println("Tên: $name")
println("Tuổi: $age")
// Biểu thức: ${expression}
println("Năm sau: ${age + 1} tuổi")
println("Tên viết hoa: ${name.uppercase()}")
println("Độ dài tên: ${name.length} ký tự")Output:
Tên: Bumbii
Tuổi: 25
Năm sau: 26 tuổi
Tên viết hoa: BUMBII
Độ dài tên: 6 ký tự📊 Thuộc tính và Methods cơ bản
Thuộc tính
val text = "Kotlin"
println(text.length) // 6 - độ dài
println(text.isEmpty()) // false
println("".isEmpty()) // true
println(text.isNotEmpty()) // true
println("".isBlank()) // true
println(" ".isBlank()) // true (chỉ có whitespace)Truy cập ký tự
val text = "Kotlin"
println(text[0]) // K (index đầu tiên)
println(text[5]) // n (index cuối cùng)
println(text.first()) // K
println(text.last()) // n
println(text.getOrNull(10)) // null (an toàn, không crash)Duyệt qua từng ký tự
val text = "Kotlin"
for (char in text) {
println(char)
}
// Với index
text.forEachIndexed { index, char ->
println("$index: $char")
}🔧 String Methods phổ biến
Chuyển đổi hoa/thường
val text = "Hello Kotlin"
println(text.uppercase()) // HELLO KOTLIN
println(text.lowercase()) // hello kotlin
println(text.replaceFirstChar { it.uppercase() }) // Hello Kotlin (capitalize)Cắt và nối
val text = " Hello Kotlin "
println(text.trim()) // "Hello Kotlin"
println(text.trimStart()) // "Hello Kotlin "
println(text.trimEnd()) // " Hello Kotlin"
// Substring
val name = "Bumbii Academy"
println(name.substring(0, 6)) // "Bumbii"
println(name.substring(7)) // "Academy"
println(name.take(6)) // "Bumbii" (6 ký tự đầu)
println(name.takeLast(7)) // "Academy" (7 ký tự cuối)
println(name.drop(7)) // "Academy" (bỏ 7 ký tự đầu)Tìm kiếm
val text = "Hello Kotlin World"
println(text.contains("Kotlin")) // true
println("kotlin" in text) // false (case-sensitive)
println(text.contains("kotlin", ignoreCase = true)) // true
println(text.startsWith("Hello")) // true
println(text.endsWith("World")) // true
println(text.indexOf("o")) // 4 (vị trí đầu tiên)
println(text.lastIndexOf("o")) // 13 (vị trí cuối cùng)Thay thế
val text = "Hello World"
println(text.replace("World", "Kotlin")) // "Hello Kotlin"
println(text.replace('o', '0')) // "Hell0 W0rld"
println(text.replaceFirst("l", "L")) // "HeLlo World"Split và Join
// Split
val csv = "apple,banana,orange"
val fruits = csv.split(",")
println(fruits) // [apple, banana, orange]
val path = "C:\\Users\\Bumbii\\Documents"
val parts = path.split("\\")
println(parts) // [C:, Users, Bumbii, Documents]
// Join
val words = listOf("Kotlin", "is", "awesome")
println(words.joinToString(" ")) // "Kotlin is awesome"
println(words.joinToString("-")) // "Kotlin-is-awesome"
println(words.joinToString(", ", "[", "]")) // "[Kotlin, is, awesome]"⚡ So sánh String
Equality
val s1 = "Kotlin"
val s2 = "Kotlin"
val s3 = "kotlin"
println(s1 == s2) // true (so sánh nội dung)
println(s1 === s2) // true (cùng reference - string pool)
println(s1 == s3) // false
println(s1.equals(s3, ignoreCase = true)) // trueComparison
val a = "apple"
val b = "banana"
println(a.compareTo(b)) // -1 (a < b theo alphabet)
println(a < b) // true🎨 Format String
String.format()
val name = "Bumbii"
val score = 95.5
val formatted = "Tên: %s, Điểm: %.1f".format(name, score)
println(formatted) // "Tên: Bumbii, Điểm: 95.5"
// Format số
val price = 15_000_000
println("Giá: %,d VNĐ".format(price)) // "Giá: 15,000,000 VNĐ"
// Padding
println("%10s".format("Hi")) // " Hi" (căn phải)
println("%-10s".format("Hi")) // "Hi " (căn trái)
println("%05d".format(42)) // "00042" (padding với 0)Format specifiers phổ biến
| Specifier | Mô tả | Ví dụ |
|---|---|---|
%s | String | ”Hello” |
%d | Integer | 42 |
%f | Float/Double | 3.14 |
%.2f | 2 decimal places | 3.14 |
%10s | Width 10, right-align | ” Hello” |
%-10s | Width 10, left-align | ”Hello “ |
%05d | Zero-padded | ”00042” |
%,d | Thousand separator | ”1,000,000” |
🛠️ Thực hành
Bài tập 1: Tạo email từ tên
fun main() {
val fullName = "Nguyễn Văn Bình"
// TODO: Tạo email dạng: [email protected]
// Hint: split, lowercase, joinToString
}Lời giải:
fun main() {
val fullName = "Nguyễn Văn Bình"
val email = fullName
.split(" ")
.joinToString(".")
.lowercase() + "@company.com"
println(email) // nguyễn.văn.bì[email protected]
// Nếu muốn remove dấu tiếng Việt, cần thêm logic
}Bài tập 2: Validate password
fun main() {
val password = "Kotlin123!"
// TODO: Kiểm tra password có:
// - Ít nhất 8 ký tự
// - Có chữ hoa
// - Có chữ thường
// - Có số
}Lời giải:
fun main() {
val password = "Kotlin123!"
val isValid = password.length >= 8 &&
password.any { it.isUpperCase() } &&
password.any { it.isLowerCase() } &&
password.any { it.isDigit() }
println("Password valid: $isValid") // true
}Bài tập 3: Parse URL
fun main() {
val url = "https://bumbii.com/kotlin/strings?page=1"
// TODO: Tách thành protocol, domain, path, query
}Lời giải:
fun main() {
val url = "https://bumbii.com/kotlin/strings?page=1"
val protocol = url.substringBefore("://")
val afterProtocol = url.substringAfter("://")
val domain = afterProtocol.substringBefore("/")
val pathAndQuery = afterProtocol.substringAfter(domain)
val path = pathAndQuery.substringBefore("?")
val query = pathAndQuery.substringAfter("?", "")
println("Protocol: $protocol") // https
println("Domain: $domain") // bumbii.com
println("Path: $path") // /kotlin/strings
println("Query: $query") // page=1
}📱 Trong Android
// Resources strings
val appName = getString(R.string.app_name)
// Plurals
val itemCount = 5
val text = resources.getQuantityString(
R.plurals.items_count,
itemCount,
itemCount
)
// SpannableString cho text formatting
val spannable = SpannableStringBuilder()
.append("Hello ")
.bold { append("Kotlin!") }
// Validation EditText
val email = emailEditText.text.toString().trim()
if (email.isBlank()) {
emailEditText.error = "Email không được để trống"
}⚠️ Lưu ý quan trọng
[!WARNING] String là immutable! Mỗi method trả về String mới:
var text = "hello" text.uppercase() // Không thay đổi text! text = text.uppercase() // Phải gán lại
[!TIP] Nối nhiều String? Dùng
StringBuilderđể tối ưu:val result = buildString { append("Hello ") append("Kotlin ") append("World!") }
✅ Checklist - Tự kiểm tra
Sau bài học này, bạn có thể:
- Tạo String với
"..."và raw string"""...""" - Sử dụng String templates:
$variablevà${expression} - Dùng
.trimIndent()và.trimMargin()cho multi-line strings - Thao tác với các methods:
split,join,replace,substring - Tìm kiếm với
contains,startsWith,endsWith,indexOf - So sánh String với
==vàequals(ignoreCase = true) - Format String với
"...".format()
Tiếp theo: Boolean và Toán tử Logic