Kotlin collection
Giới thiệu
Khác với các nhiều ngôn ngữ khác, Kotlin phân biệt rõ ràng giữa collection có thể thay đổi giá trị và collection không thể thay đổi giá trị(list
, set
, map
...). Bởi vậy, việc control chính xác lúc nào dùng loại collection thế nào sẽ giúp giảm thiểu bug và việc thiết kế các API được tốt hơn.
Kotlin cung cấp cho chúng ta một tập các native interface để làm việc với collection:
Iterable: Lớp cha. Bất kỳ class nào kế thừa từ interface này đại diện cho một chuỗi các phần tử mà chúng ta có thể duyệt qua
MutableIterable:
Iterable
hỗ trợ việc xóa các phần tử trong khi đanh duyệtCollection: Class đại diện cho một tập các phần tử. Chúng ta có thể truy cập đến các hàm mà trả về size của collection, kiểm tra collection có rỗng hay không,... Tất cả các method cho loại này chỉ là lấy dữ liệu, bởi vì collection là immutable.
MutableCollection:
Collection
hỗ trợ việc thêm hoặc xóa các phần tử: các hàmadd
,remove
,clear
...List: Collection có lẽ là được dùng nhiều nhất. Nó đại diện cho một tập các phần tử có thứ tự. Bởi vì có thứ tự, ta có thể truy cập các phần tử thông qua chỉ số
MutableList:
List
hỗ trợ việc thêm hoặc xóa các phần tửSet: một tập các phần tử không có thứ tự và không hỗ trợ lưu các phần tử trùng
MutableSet:
Set
hỗ trợ việc thêm và xóa các phần tửMap: một tập các cặp key - value với key trong map là duy nhất
MutableMap:
Map
hỗ trợ việc thêm và xóa các phần tử
Với 2 kiểu collection này, ta cần phân biệt rõ ràng giữa các khái niệm read only view của mutable collection và một collection thực sự immutable. Phần này sẽ được nói ở sau
Khởi tạo
List<out T>
trong Kotlin là một interface cung cấp các thao tác như size
, get
.... Cũng như trong Java, List<out T>
kế thừa từ Collection<T>
và Iterable<T>
. Đây là immutable collection.
Vì collection không thể thay đổi, chúng chỉ có thể khởi tạo giá trị lúc khai báo. Kotlin cung cấp hàm khởi tạo hoặc chúng ta có thể sử dụng hàm thư viện chuẩn có sẵn listOf()
, setOf()
và mapOf()
. Với mapOf()
, ta sử dụng cú pháp mapOf(a to b, c to d)
. Cùng với đó, các hàm add()
, clear()
cũng sẽ không có đối với immutable collection.
Với mutable collection, chúng ta có MutableList<T>
, interface này cung cấp thêm các thao tác như add
, clear
... Việc phân chia cũng tương tự với Set<out T>/MutableSet<T>
và Map<K, out V>/MutableMap<K, V>
.
Phân biệt
Chúng ta cùng xem vd sau:
readOnlyView
không thể thay đổi giá trị của list mà chỉ có thể xem được giá trị của list. Giá trị của list thay đổi khi numbers
thay đổi giá trị bằng cách sử dụng add
hoặc clear
. Khi đó, giá trị của readOnlyView
khi in ra cũng sẽ thay đổi. Điều đó bởi vì cả 2 biến numbers
và readOnlyView
đều cùng trỏ vào cùng một list và readOnlyView
sẽ thay đổi nếu list được trỏ vào thay đổi. Trong trường hợp chỉ có duy nhất 1 tham chiếu tới list, chúng ta có thể coi collection đó hoàn toàn là immutable collection.
Trong trường hợp bạn chỉ muốn thay đổi collection ở bên trong đối tượng mà không muốn bị thay đổi từ bên ngoài:
Một số extension method quen thuộc
Với map
, ta có thể khởi tạo và truy cập như sau:
Một số hàm phổ biến
Đây là các hàm nằm trong thư viện chuẩn được Kotlin cung cấp với nhiều loại collection khác nhau
Các hàm làm việc với tổng thể
any
Trả về true
nếu có ít nhất 1 phần tử thỏa mãn logic truyền vào
all
Trả về true
nếu tất cả các phần tử thỏa mãn logic truyền vào
count
Trả về số phần tử thỏa mãn logic truyền vào
fold
Tổng của các giá trị bắt đầu từ giá trị khởi tạo và áp dụng việc tính toán ở hàm được đưa vào với các phần tử từ đầu đến cuối collection.
Như ở ví dụ trên: 0
là giá trị khởi tạo, total
là tổng của quá trình, i
là giá trị của từng phần tử, lần lượt là 3
, 5
, 6
foldRight
Tương tự như fold
nhưng duyệt theo thứ tự từ cuối trở về đầu
Giá trị lần lượt của i
bây giờ là: 6
, 5
, 3
forEach
Thực hiện hàm được truyền vào với mỗi phần tử trong collection:
forEachIndexed
Tương tự như forEach
, tuy nhiên có thêm chỉ số của các phần tử:
max
Trả về phần tử lớn nhất của collection hoặc null
nếu collection rỗng
min
Trả về phần tử nhỏ nhất của collection hoặc null
nếu collection rỗng
none
Trả về true
nếu không có phần tử nào thỏa mãn logic truyền vào
reduce
Tương tự như fold
nhưng không có giá trị khởi tạo mà chỉ áp dụng với các phần tử của dãy
reduceRight
Tương tự như reduce
nhưng duyệt từ cuối dãy trở về đầu
sumBy
Trả về tổng của tất cả các phần tử nhưng được xử lý thông qua logic được truyền vào
result
ở trên là tổng của các số dư của dư của từng phần tử
Các hàm lọc
drop
Trả về một list bao gồm tất cả các phần tử trừ n phần tử đầu tiên
dropWhile
Trả về một list bao gồm tất cả các phần tử trừ các phần tử đầu tiên mà thỏa mãn logic truyền vào
Trong ví dụ trên, các phần từ đầu tiên mà thỏa mãn yêu cầu sẽ bị loại ra.
dropLastWhile
Tương tự như dropWhile
tuy nhiên sẽ loại các phần tử cuối nếu thỏa mãn logic truyền vào
filter
Trả về một list các phần tử thỏa mãn logic truyền vào
filterNot
Trả về một list các phần tử không thỏa mãn logic truyền vào
filterNotNull
Trả về một list các phần tử trừ các phần tử null
slice
Trả về một list các phần tử ở các vị trí xác định
take
Trả về một list gồm n phần tử đầu tiên
takeLast
Trả về một list gồm n phần tử cuối cùng
takeWhile
Trả về một list bao gồm các phần tử đầu tiên mà thỏa mãn logic truyền vào
Các hàm chuyển đổi
flatMap
Duyệt qua tất cả các phần tử và tạo ra một collection mới cho mỗi phần tử bằng cách áp dụng logic truyền vào, cuối cùng trả về một list bao gồm tất cả các phần tử của các list vừa được tạo ra
groupBy
Trả về một map bằng cách áp dụng logic truyền vào và phân loại các phần tử trong collection thành các nhóm
map
Trả về một list là kết quả của logic chuyển đổi được truyền vào áp dụng với tất cả các phần tử của collection ban đầu
mapIndexed
Trả về một list là kết quả của logic chuyển đổi được truyền vào áp dụng với tất cả các phần tử và chỉ số của các phần tử của collection ban đầu
Các hàm làm việc với các phần tử
contains
Trả về true
nếu phần tử nằm trong collection
elementAt
Trả về phần tử tại vị trí i hoặc throw IndexOutOfBoundException
nếu i không nằm trong khoảng chỉ số của collection
elementAtOrElse
Trả về một phần tử ở vị trí i hoặc thực hiện logic được truyền vào nếu chỉ số của collection không nằm trong khoảng chỉ số của collection
elementAtOrNull
Trả về một phần tử ở vị trí i hoặc null
nếu chỉ số nằm ngoài khoảng chỉ số của collection
first
Trả về phần tử đầu tiên thỏa mãn logic truyền vào hoặc throw NoSuchElementCollection
nếu không có phần tử thỏa mãn logic
firstOrNull
Trả về giá trị đầu tiên thỏa mãn logic truyền vào hoặc trả về null
nếu không có phần từ nào thỏa mãn logic
indexOf
Trả về chỉ số đầu tiên của phần tử i hoặc trả về -1
nếu không có phần tử nào được tìm thấy
indexOfFirst
Trả về chỉ số đầu tiên của phần tử i thỏa mãn logic truyền vào hoặc trả về -1
nếu không tìm thấy phần tử nào
indexOfLast
Trả về chỉ số của phần tử cuối cùng thỏa mãn logic truyền vào hoặc trả về -1
nếu không tìm thấy phần tử nào
last
Trả về phần tử cuối cùng thỏa mãn logic truyền vào
lastIndexOf
Trả về chỉ số cuối cùng của phần tử thỏa mãn logic hoặc -1
nếu không tìm thấy phần tử nào
lastOrNull
Trả về phần tử cuối cùng thỏa mãn logic hoặc null
nếu không tìm thấy phần tử nào
single
Trả về phần tử duy nhất thỏa mãn logic truyền vào, throw NoSuchElementCollection
nếu không có phần tử nào thỏa mãn logic hoặc throw IllegalArgumentException
nếu có nhiều hơn một phần tử thỏa mãn logic
singleOrNull
Trả về phần tử duy nhất thỏa mãn logic truyền vào và trả về null
nếu không có phần tử nào thỏa mãn logic hoặc có nhiều hơn một phần tử thỏa mãn logic
Các hàm sinh
partition
Chia collection ban đầu thành một cặp collection(Pair) với collection đầu tiên chứa những phần tử mà logic truyền vào trả về true
còn collection thứ hai chứa những phần tử mà logic truyền vào trả về false
plus
Trả về một collection mới bao gồm tất cả các phần tử của collection ban đầu và collection được truyền vào. Vì hàm plus
là hàm overload của toán tử +
nên ta có thể sử dụng toán tử +
zip
Trả về một collection mới là collection của một cặp (Pair) bằng cách kết hợp từng phần tử của collection ban đầu với từng phần tử của collection được truyền vào. Size của collection mới bằng size của collection có size nhỏ hơn
Các hàm làm việc với thứ tự
reverse
Trả về một collection với thứ tự các phần tử bị đảo ngược lại
sorted
Trả về một list đã được sắp xếp theo chiều tăng dần
sortedBy
Trả về một list các phần tử được sắp xếp bằng logic truyền vào, những phần tử thỏa mãn logic sẽ được xếp vào cuối, những phần tử không thỏa mãn được xếp vào đầu
sortedDescending
Trả về một list đã được sắp xếp theo chiều giảm dần
sortedByDescending
Trả về một list các phần tử được sắp xếp bằng logic truyền vào, những phần tử thỏa mãn logic sẽ được xếp vào đầu, những phần tử không thỏa mãn được xếp vào cuối