Chào mừng bạn đến với Cafedev, nơi chúng tôi chia sẻ về thế giới đa dạng và phong phú của lập trình Kotlin. Collections, hay bộ sưu tập, chính là “kho báu” mà mọi lập trình viên Kotlin đều muốn hiểu rõ. Từ list đến map, chúng là công cụ mạnh mẽ giúp bạn tổ chức và xử lý dữ liệu một cách hiệu quả. Hãy cùng Cafedev khám phá sâu hơn về Collections trong Kotlin, đưa ra những cách sử dụng thông minh và hiệu quả cho dự án của bạn.

Trong lập trình, có ích khi có khả năng nhóm dữ liệu vào các cấu trúc để xử lý sau này. Và Kotlin cung cấp các kiểu bộ sưu tập cho mục đích này.
Kotlin có các bộ sưu tập sau:

Loại bộ sưu tậpMô tả
Danh sách(List)Bộ sưu tập có thứ tự giữa các phần tử(mục)
Tập hợp(Set)Bộ sưu tập không trùng lặp trong các phần tử(mục)
Bản đồ(Map)Bộ sưu tập các cặp khóa-giá trị trong đó các khóa là duy nhất và ánh xạ chỉ đến một giá trị

Mỗi kiểu bộ sưu tập sẽ có thể thay đổi được hoặc chỉ đọc giá trị bằng cách dùng cú pháp val or var.

1. Kiểu dự liệu Danh sách – List

Danh sách lưu trữ các mục theo thứ tự chúng được thêm vào và cho phép các mục trùng lặp.
Để tạo một danh sách chỉ đọc (List) mà không thêm bớt các mục được thì sử dụng hàm listOf().
Để tạo một danh sách có thể thay đổi (MutableList), sử dụng hàm mutableListOf().
Khi tạo danh sách, Kotlin có thể suy ra loại của các mục được lưu trữ. Để khai báo kiểu một cách rõ ràng, thêm kiểu dữ liệu trong dấu ngoặc nhọn <> sau khai báo danh sách:

fun main() {
//sampleStart
// Read only list
val readOnlyShapes = listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]

// Mutable list with explicit type declaration
val shapes: MutableList = mutableListOf("triangle", "square", "circle")
println(shapes)
// [triangle, square, circle]
//sampleEnd
}

Để ngăn chặn sửa đổi không mong muốn, bạn có thể khai báo chỉ đọc cho danh sách có thể thay đổi bằng cách gán chúng cho một List:

val shapes: MutableList = mutableListOf("triangle", "square", "circle")
val shapesLocked: List = shapes

Điều này còn được gọi là ép kiểu.

Danh sách có thứ tự nên để truy cập một mục trong danh sách, sử dụng toán tử truy cập được chỉ định sau []:

fun main() {
//sampleStart
val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes[0]}")
// The first item in the list is: triangle
//sampleEnd
}

Để lấy mục đầu tiên hoặc cuối cùng trong danh sách, sử dụng các hàm .first() và .last() tương ứng:

fun main() {
//sampleStart
val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes.first()}")
// The first item in the list is: triangle
//sampleEnd
}

.first() và .last() là các ví dụ về hàm mở rộng. Để gọi một hàm mở rộng trên một đối tượng, viết tên hàm như sau: Sau đối tượng được thêm vào với một dấu chấm ..
Để biết thêm thông tin về hàm mở rộng, xem Hàm mở rộng. Đối với mục đích của bài hướng dẫn này, bạn chỉ cần biết cách gọi chúng là được rồi, để hiểu hơn bạn có thể tham khảo các bài chi tiết về nó trong các bài tiếp theo.

Để lấy số lượng mục trong danh sách, sử dụng hàm .count():

fun main() {
//sampleStart
val readOnlyShapes = listOf("triangle", "square", "circle")
println("This list has ${readOnlyShapes.count()} items")
// This list has 3 items
//sampleEnd
}

Để kiểm tra xem một mục có trong danh sách hay không, sử dụng toán tử in:

fun main() {
//sampleStart
val readOnlyShapes = listOf("triangle", "square", "circle")
println("circle" in readOnlyShapes)
// true
//sampleEnd
}

Để thêm hoặc xóa mục từ danh sách có thể thay đổi, sử dụng các hàm .add().remove() tương ứng:

fun main() {
//sampleStart
val shapes: MutableList = mutableListOf("triangle", "square", "circle")
// Add "pentagon" to the list
shapes.add("pentagon")
println(shapes)
// [triangle, square, circle, pentagon]
// Remove the first "pentagon" from the list
shapes.remove("pentagon")
println(shapes)
// [triangle, square, circle]
//sampleEnd
}

2. Kiểu dự liệu tập hợp – Set

Trong khi danh sách(List) có thứ tự và cho phép các mục trùng lặp, còn tập hợp thì không có thứ tự và chỉ lưu trữ các mục duy nhất.

Để tạo một tập hợp chỉ đọc (Set) và không tuỳ chỉnh thêm bớt được, sử dụng hàm setOf().
Để tạo một tập hợp có thể thay đổi dùng (MutableSet), sử dụng hàm mutableSetOf().
Khi tạo tập hợp, Kotlin có thể tự suy ra loại của các mục được lưu trữ. Để khai báo loại một cách rõ ràng, thêm loại trong dấu ngoặc nhọn <> sau khai báo tập hợp:

fun main() {
//sampleStart
// Read-only set
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
// Mutable set with explicit type declaration
val fruit: MutableSet = mutableSetOf("apple", "banana", "cherry", "cherry")
println(readOnlyFruit)
// [apple, banana, cherry]
//sampleEnd
}

Bạn có thể thấy trong ví dụ trước đó rằng vì tập hợp chỉ chứa các phần tử duy nhất, phần tử "cherry" trùng lặp đã bị loại bỏ.

Để ngăn chặn sửa đổi không mong muốn, có thể tạo một tập hợp chỉ đọc từ tập hợp có thể thay đổi bằng cách ép kiểu chúng thành Set:

val fruit: MutableSet = mutableSetOf("apple", "banana", "cherry", "cherry")
val fruitLocked: Set = fruit

Vì tập hợp là không có thứ tự, bạn không thể truy cập một mục tại một chỉ số cụ thể.
Để lấy số lượng mục trong một tập hợp, sử dụng hàm .count():

fun main() {
//sampleStart
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("This set has ${readOnlyFruit.count()} items")
// This set has 3 items
//sampleEnd
}

Để kiểm tra xem một mục có trong tập hợp hay không, sử dụng toán tử in:

fun main() {
//sampleStart
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("banana" in readOnlyFruit)
// true
//sampleEnd
}

Để thêm hoặc xóa mục từ tập hợp có thể thay đổi, sử dụng các hàm .add().remove() tương ứng:

fun main() {
//sampleStart
val fruit: MutableSet = mutableSetOf("apple", "banana", "cherry", "cherry")
fruit.add("dragonfruit") // Add "dragonfruit" to the set
println(fruit) // [apple, banana, cherry, dragonfruit]

fruit.remove("dragonfruit") // Remove "dragonfruit" from the set
println(fruit) // [apple, banana, cherry]
//sampleEnd
}

3. Kiểu dự liệu bản đồ – Map

Bản đồ(Map) lưu trữ các mục dưới dạng các cặp khóa-giá trị(key:value). Bạn truy cập giá trị bằng cách tham chiếu đến khóa. Bạn có thể tưởng tượng một map như một thực đơn thức ăn. Bạn có thể tìm giá (giá trị) bằng cách tìm chìa (khóa) bạn muốn ăn. Bản đồ hữu ích nếu bạn muốn tra cứu một giá trị mà không sử dụng một chỉ số.

Mỗi khóa trong một bản đồ phải là duy nhất để Kotlin có thể hiểu bạn muốn lấy giá trị nào.

Bạn có thể có các giá trị trùng lặp trong một bản đồ.

Để tạo một bản đồ chỉ đọc (Map), sử dụng hàm mapOf().
Để tạo một bản đồ có thể thay đổi (MutableMap), sử dụng hàm mutableMapOf().
Khi tạo bản đồ, Kotlin có thể suy ra loại của các mục được lưu trữ. Để khai báo loại một cách rõ ràng, thêm loại của khóa và giá trị trong dấu ngoặc nhọn <> sau khai báo bản đồ. Ví dụ: MutableMap<string, int>. Các khóa có loại là String và các giá trị có loại là Int.
Cách dễ nhất để tạo bản đồ là sử dụng to giữa mỗi khóa và giá trị liên quan của nó:

fun main() {
//sampleStart
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {apple=100, kiwi=190, orange=100} 

 
 

// Mutable map with explicit type declaration
val juiceMenu: MutableMap<string, int=""> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {apple=100, kiwi=190, orange=100}
//sampleEnd
}</string,>

Để ngăn chặn sửa đổi không mong muốn, muốn biến thành map chỉ đọc từ map có thể thay đổi bằng cách ép kiểu chúng thành Map:

val juiceMenu: MutableMap<string, int=""> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
val juiceMenuLocked: Map<string, int=""> = juiceMenu

Để truy cập giá trị trong một bản đồ, sử dụng toán tử truy cập được chỉ định: [] với khóa của nó:

fun main() {
//sampleStart
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("The value of apple juice is: ${readOnlyJuiceMenu["apple"]}")
// The value of apple juice is: 100
//sampleEnd
}

  
fun main() {
//sampleStart
// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("This map has ${readOnlyJuiceMenu.count()} key-value pairs")
// This map has 3 key-value pairs
//sampleEnd
}

Để thêm hoặc xóa mục từ một bản đồ có thể thay đổi, sử dụng các hàm .put().remove() tương ứng:

  

fun main() {
//sampleStart
val juiceMenu: MutableMap<string, int=""> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu.put("coconut", 150) // Add key "coconut" with value 150 to the map
println(juiceMenu)
// {apple=100, kiwi=190, orange=100, coconut=150}</string,>
 

juiceMenu.remove("orange") // Remove key "orange" from the map
println(juiceMenu)
// {apple=100, kiwi=190, coconut=150}
//sampleEnd
}

Để kiểm tra xem một khóa cụ thể đã có trong một bản đồ đó chưa, sử dụng hàm .containsKey():

fun main() {
//sampleStart
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.containsKey("kiwi"))
// true
//sampleEnd
}

Để có được một bộ sưu tập của các khóa hoặc giá trị của một bản đồ(map), sử dụng các thuộc tính keysvalues tương ứng:

fun main() {
//sampleStart
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.keys)
// [apple, kiwi, orange]
println(readOnlyJuiceMenu.values)
// [100, 190, 100]
//sampleEnd
}

keys và values là các ví dụ về thuộc tính của một đối tượng. Để truy cập thuộc tính của một đối tượng, viết tên thuộc tính sau đó là đối tượng được thêm vào với một dấu chấm ..
Thuộc tính được thảo luận chi tiết hơn trong bài về Class.
Để kiểm tra xem một khóa hoặc giá trị có trong một bản đồ(map) hay không, sử dụng toán tử in

fun main() {
//sampleStart
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("orange" in readOnlyJuiceMenu.keys)
// true
println(200 in readOnlyJuiceMenu.values)
// false
//sampleEnd
}

Để biết thêm về những gì bạn có thể làm với các bộ sưu tập, xem các bài giới thiệu chi tiết hơn về các Bộ sưu tập trong Kotlin.
Bây giờ bạn đã biết về các loại cơ bản và cách quản lý các bộ sưu tập, đến lúc khám phá Luồng điều khiển mà bạn có thể sử dụng trong chương trình của mình.

4. Thực hành

4.1 Bài tập 1

Bạn có một danh sách các số màu “green” và một danh sách các số màu “red”. Hoàn tất code để in ra có bao nhiêu số tổng cộng.

fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
// Write your code here
}

Gợi ý:

fun main() {
val greenNumbers = listOf(1, 4, 23)
val redNumbers = listOf(17, 2)
val totalCount = greenNumbers.count() + redNumbers.count()
println(totalCount)
}

4.2 Bài tập 2

Bạn có một tập hợp các giao thức được hỗ trợ bởi máy chủ của bạn. Người dùng yêu cầu sử dụng một giao thức cụ thể. Hoàn tất chương trình để kiểm tra xem giao thức được yêu cầu có được hỗ trợ hay không (isSupported phải là một giá trị Boolean).

fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = // Write your code here
println("Support for $requested: $isSupported")
}

Đảm bảo rằng bạn kiểm tra giao thức được yêu cầu ở dạng chữ in hoa. Bạn có thể sử dụng hàm .uppercase() để giúp bạn làm điều này.

Gợi ý:

fun main() {
val SUPPORTED = setOf("HTTP", "HTTPS", "FTP")
val requested = "smtp"
val isSupported = requested.uppercase() in SUPPORTED
println("Support for $requested: $isSupported")
}

4.3 Bài tập 3

Định nghĩa một bản đồ liên quan đến các số nguyên từ 1 đến 3 với cách viết tương ứng của chúng. Sử dụng bản đồ này để viết số được đưa ra.

fun main() {
val number2word = // Write your code here
val n = 2
println("$n is spelt as '${}'")
}

Gợi ý:

fun main() {
val number2word = mapOf(1 to "one", 2 to "two", 3 to "three")
val n = 2
println("$n is spelt as '${number2word[n]}'")
}

-> Kho tài liệu Free học Kotlin từ A->Z

Cuối cùng,

Cảm ơn bạn đã thăm Cafedev và theo dõi bài viết về Collections trong Kotlin. Chúng tôi hy vọng rằng thông tin và hướng dẫn mà chúng tôi chia sẻ sẽ giúp bạn nắm vững và ứng dụng linh hoạt trong dự án của mình. Đừng ngần ngại đặt câu hỏi hoặc chia sẻ ý kiến tại Cafedev để cùng nhau tạo nên một cộng đồng lập trình mạnh mẽ. Hãy tiếp tục theo dõi chúng tôi để cập nhật những thông tin mới nhất và những bài viết hữu ích khác từ Cafedev.

Các nguồn kiến thức MIỄN PHÍ VÔ GIÁ từ cafedev tại đây

Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của Cafedev để nhận được nhiều hơn nữa:

Chào thân ái và quyết thắng!

Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you!