Mở bài

Tóm tắt phần 1, mình đã đi qua các kiểu dữ liệu cơ bản từ khái niệm cơ bản đến cách tạo 1 biến và trường hợp sử dụng. Nay mình sẽ đi đến 2 kiểu dữ liệu cuối cùng trong danh sách kiểu dữ liệu của Kotlin. Arrays và String.

Arrays (Mảng)

1. Khai báo

Như trong Java, kiểu dữ liệu arrays là 1 tập hợp các giá trị cùng kiểu dữ liệu. Tuy nhiên, cách khởi tạo mảng trong Kotlin hoàn toàn khác với Java:

val cars = arrayOf("Volvo", "BMW", "Ford", "Mazda")

Hoặc 1 cách tuỳ chọn khác với định dạng kiểu dữ liệu đi kèm

val cars = arrayOf<String>("Volvo", "BMW", "Ford", "Mazda")

Nếu trong Java trước đây chỉ sử dụng [] để tạo mảng thì nay Kotlin lại có 1 cách tường minh hơn với keyword arrayOf.

Ngoài 2 cách tạo arrays phía trên, mình cũng có thể tạo 1 array với kiểu Integer như sau:

val numbers = intArrayOf(10, 16, 18, 20, 27, 28)

Có quá nhiều cách tạo Array trong Kotlin, vậy kiểu nào là tối ưu nhất?

2. Tuỳ chọn (Optional)

Câu trả lời là không có! Không có cái nào tối ưu hơn cái nào cả, tất cả phù thuộc vào thói quen của mỗi người.

Nếu như trước đây, lúc Kotlin vừa mới ra đời (năm 2011), chỉ tồn tại 1 cách tạo duy nhất là sử dụng keyword arrayOf thì nay, với cộng đồng Kotlin phát triển mạnh, các kiểu tạo array tích hợp được ra đời: intArrayOf(), charArrayOf(), floatArrayOf()… để phục vụ các tác vụ dễ dàng hơn. Nhưng về bản chất, các phương thức tích hợp này không khác gì với arrayOf<Int>(), arrayOf<Char>(), arrayOf<Float>()…

Chú ý thêm: còn 1 phương thức khá đặt biệt chỉ có trong Kotlin đó là arrayOfNulls() giúp tạo 1 mảng với đầy giá trị null bên trong.

3. Cách sử dụng

Kotlin Arrays cũng cung cấp 1 số phương thức mạnh mẽ đi kèm, để hỗ trợ việc truy vấn dữ liệu; kiểm tra dữ liệu; copy dữ liệu…

a. Setter và Getter

Về việc truy cập giá trị bên trong mảng cũng có phần giống với Java - đều sử dụng chỉ mục (index) - tất cả giá trị trong mảng đều bắt đầu chỉ mục đầu tiên là 0.

Để truy cập vào giá trị đầu tiên của mảng:

println(cars[0])

Cách khác, Kotlin còn cung cấp 2 phương thức set()get() để tương tác với chỉ mục của array 1 cách minh bạch hơn.

val fruits = arrayOf<String>("Apple", "Mango", "Banana", "Orange")

println(fruits.get(0)) // Apple
println(fruits.get(3)) // Orange

//set the value at 3rd index
fruits.set(3, "Guava")
println(fruits.get(3)) // Guava

b. Length và Count

Với trường hợp kiểm tra độ dài của 1 mảng, Kotlin Array cung cấp cho mình phương thức khá quen thuộc để kiểm tra độ dài của mảng: size()

val fruits = arrayOf<String>("Apple", "Mango", "Banana", "Orange")

println(fruits.size) // 4

Khác với index, size() là đếm số lượng, nên sẽ bắt đầu từ 1, không phải 0. Ngoài ra còn có thể sử dụng count(), chức năng tương tự như size()

c. Loop

Tương tự Java, mình có thể sử dụng vòng lặp để lặp qua từng phần tử trong array.

val fruits = arrayOf<String>("Apple", "Mango", "Banana", "Orange")

for(item in fruits){
  print("$item, ")
}

// Apple, Mango, Banana, Orange,

Đừng quá quan tâm về cú pháp vòng for ở trên, mình sẽ có bài viết về nó sau này.

d. Kiểm tra rỗng

Kotlin cũng cung cấp mạnh mẽ phương thức kiểm tra xem mảng đó có rỗng hay không với isEmpty()

val fruits = arrayOf<String>()

println("Array is empty: ${fruits.isEmpty()}")

// Array is empty: true

e. Một số phương thức khác

Ngoài các phương thức tiêu biểu ở trên, Kotlin cung cấp các phương thức hỗ trợ khác giúp lập trình viên có thể làm việc với Array dễ dàng hơn như: drop(), dropLast(), distinct(),…

String (Chuỗi)

Chuỗi là 1 dãy ký tự. Ví dụ Hi Mom! được xem là 1 chuỗi.

Trong Kotlin, 1 chuỗi được xem là 1 đối tượng (object) được tạo dựng từ lớp String. Nghĩa là câu Hi Mom! ở trên được xem là 1 thể hiện (instance) của lớp String.

Mình sẽ nói chi tiết về class (lớp) trong mục Kotlin Advanced.

1. Tạo biến

Cách tạo biến String rất đơn giản:

val myWorld = "Hi Mom!"

Tại đây, biến myWorld sau khi khởi tạo giá trị ban đầu (initial value) sẽ được định dạng là kiểu dữ liệu String.

Mình cũng có thể khai báo kiểu dữ liệu trước khi khởi tạo giá trị ban đầu cho biến:

val myHero: String
// ...

myHero = "Mommy"

2. Truy cập vào giá trị của biến

Với String, việc truy cập giá trị bên trong biến tương tự với Arrays, đó là sử dụng chỉ mục.

val myWorld = "Hi Mom!"

var item = myWorld[1] // 'i'

Lưu ý: nếu truy cập vào chỉ mục lớn hơn chỉ mục của chuỗi sẽ tạo ra lỗi chương trình.

val myWorld = "Hi Mom!"
var item: Char

item = myWorld[3] // 'M'
item = myWorld[999] // Error! String index is out of range

Ngoài ra, mình có thể sử dụng vòng lặp cho biến String tương tự Array.

val myHero = "Mommy"

for (item in myHero) {
  print("$item, ")
}

// 'M', 'o', 'm', 'm', 'y',

3. Tính bất biến trong String

Giống với Java, kiểu dữ liệu String trong Kotlin được xem là bất biến (immutable).

Xem lại Tính bất biến và khả biến trong lập trình

val myHero = "Mom"
myHero = "Someone else" // Error!

Tuy nhiên, nếu sử dụng từ khoá var thì vẫn có thể thay đổi được giá trị của biến.

var villain = "rob"
println(villain) // rob

villain = "Bad person"
println(villain) // Bad person

Nếu như vậy, thì nó ngược lại với tính bất biến rồi? Không, thực chất biến villain cũ vẫn ở đó, nó chỉ tạo ra thêm 1 vùng nhớ mới để lưu trữ biến villain thứ 2 thôi. Điều này là hoàn toàn không khuyến khích khi sử dụng String.

Việc tạo ra nhiều vùng nhớ chỉ để lưu trữ các giá trị chỉ dùng 1 lần là lãng phí, và khiến ứng dụng mình chạy chậm hơn. Giả sử nếu mình chỉ định lại (reassign) giá trị nhiều lần sẽ tạo ra vô số vùng nhớ lưu trữ nhưng chỉ sử dụng 1 lần; việc này không nên xảy ra.

Vì vậy, Kotlin đã cung cấp cho mình 1 phương thức hỗ trợ việc tạo biến String không sinh ra vùng nhớ mới: buildString()

val myHero = buildString {
  for (item in "Mommy") {
    append(item)
    println("item: $item")
  }
}
println()
println("final: $myHero")

/* 
item: M
item: o
item: m
item: m
item: y

final: Mommy
*/ 

4. String templates literal

Kotlin có 1 tính năng mạnh mẽ khác mà Java không có; đó là nối chuỗi bằng $.

val myWorld = "Mom!"

println("Hi $myWorld") // Hi Mom!

Kết

Như vậy, là mình đã đi qua các khái niệm cơ bản của Kotlin trước khi đi vào các bài học nâng cao hơn. Đây không phải toàn bộ kiểu dữ liệu có trong Kotlin, nhưng đây là các kiểu dữ liệu cơ bản nhất và thông dụng nhất trong Kotlin. Phần sau mình sẽ đến phần các câu điều kiện trong Kotlin.


Kaiz on Github