陣列
陣列是一種資料結構,用於持有固定數量的相同型別或其子型別的值。 陣列元素是有序的,並且可以透過索引來存取。
Kotlin 提供了 Array<T> 類別以及 基本型別陣列。
何時使用陣列
在需要與 Java API 互通或有低階需求時,請使用陣列。例如,如果您的效能需求超出了常規應用程式的需要,或者您需要建構自訂的資料結構。
對於大多數的使用案例,請改用集合。
| 功能性 | 陣列 | 集合 |
|---|---|---|
| 大小 | 固定 | 取決於型別 |
| 唯讀變體 | 否,始終是可變的 | 是 (List 與 Set) |
| 新增與移除元素 | 無原生支援。 需分配並複製到新陣列 | 是 (可變集合) |
使用 == 進行結構相等性比較 | 否,比較的是參考。 請改用 .contentEquals() | 是 |
| 基本型別值 | 基本型別陣列儲存值 不會進行裝箱 (boxing) | 通常會被裝箱 |
| Java 互通性 | 對應至 T[] | 對應至 java.util.List 與java.util.Set |
| 函式式風格的篩選與 轉換 | 有限 | 廣泛 |
了解如何將陣列轉換為集合。
建立陣列
要建立陣列,您可以使用:
arrayOf()、arrayOfNulls()或emptyArray()函式。Array建構函式。
使用
val宣告陣列僅能防止重新指派變數,但不會使內容變為唯讀。 無論是在val還是var陣列中,元素都是可變的。這兩者的區別僅影響參考,而不影響內容。 若要使用唯讀檢視,請改用集合。
帶有值的陣列
要從一組已知的值建立型別化陣列,請使用 arrayOf() 函式。 Kotlin 會自動推論型別:
fun main() {
val simpleArray = arrayOf(1, 2, 3) // Array<Int>
println(simpleArray.joinToString())
// 1, 2, 3
}空陣列
要建立一個沒有元素的陣列,請使用 emptyArray() 函式。 您可以在指派的左側或右側指定元素的型別:
val emptyArrayRight = emptyArray<String>()
val emptyArrayLeft: Array<String> = emptyArray()了解如何新增元素到陣列。
帶有 null 的陣列
要建立一個指定大小且填滿 null 元素的陣列, 請使用 arrayOfNulls() 函式:
fun main() {
val nullArray: Array<Int?> = arrayOfNulls(3)
println(nullArray.joinToString())
// null, null, null
}Array 建構函式
Array 建構函式接受陣列大小,以及一個傳回陣列元素值的函式:
fun main() {
val zeroes = Array<Int>(3) { 0 }
println(zeroes.joinToString())
// 0, 0, 0
val squares = Array(5) { i -> i * i }
println(squares.joinToString())
// 0, 1, 4, 9, 16
}巢狀陣列
要建立巢狀或多維陣列,請使用陣列的陣列。 巢狀陣列不需要是相同的型別或相同的大小。
fun main() {
// 建立一個二維陣列
val twoDArray = Array(2) { Array<Int>(2) { 0 } }
println(twoDArray.contentDeepToString())
// [[0, 0], [0, 0]]
// 建立一個三維陣列
val threeDArray = Array(3) { Array(3) { Array<Int>(3) { 0 } } }
println(threeDArray.contentDeepToString())
// [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
}基本型別陣列
如果您在 Array 類別中使用基本型別值,編譯器會將這些值裝箱 (box) 成物件。 為了避免裝箱開銷,您可以使用專用的基本型別陣列。 它們不是 Array<T> 類別的子類別,但它們提供了類似的函式和屬性集。
| Kotlin 型別 | Java 等效項 |
|---|---|
BooleanArray | boolean[] |
ByteArray | byte[] |
CharArray | char[] |
DoubleArray | double[] |
FloatArray | float[] |
IntArray | int[] |
LongArray | long[] |
ShortArray | short[] |
Kotlin 沒有專用的
StringArray型別。由於String不是基本型別, 請改用arrayOf()或arrayOf<String>()函式並配合型別推論。
要建立基本型別陣列,請使用以下選項之一:
建構函式:
kotlinfun main() { // 建立一個大小為 5 且值初始化為零的 Int 陣列 val primitiveTypeArray = IntArray(5) println(primitiveTypeArray.joinToString()) // 0, 0, 0, 0, 0 // 建立一個 Int 陣列並接受一個初始設定式函式 val squares = IntArray(5) { i -> i * i } println(squares.joinToString()) // 0, 1, 4, 9, 16 }工廠函式:
kotlinfun main() { // 建立一個有 5 個元素的 Int 陣列 val numbers = intArrayOf(1, 2, 3, 4, 5) println(numbers.joinToString()) // 1, 2, 3, 4, 5 // 建立一個有 3 個元素的 Char 陣列 val characters = charArrayOf('K', 't', 'l') println(characters.joinToString()) // K, t, l // 建立一個有 3 個元素的 Double 陣列 val doubles = doubleArrayOf(0.22, 4.16, 0.5) println(doubles.joinToString()) // 0.22, 4.16, 0.5 }
要將基本型別陣列轉換為物件型別陣列,請使用
.toTypedArray()函式。要將物件型別陣列轉換為基本型別陣列,請使用
.toBooleanArray()、.toByteArray()、.toCharArray()等。
使用陣列
陣列支援許多與集合相同的操作,包括迭代、搜尋、排序和轉換。 在 Kotlin 中,您可以透過將陣列用於向函式傳遞可變數量的引數,或對陣列本身執行操作來使用陣列。 下表列出了最常用的屬性和函式:
| 成員 | 傳回 |
|---|---|
size | 元素數量 |
indices | 有效索引的範圍 |
lastIndex | 最後一個有效索引 |
first() 與 last() | 第一個與最後一個元素 |
isEmpty() 與 isNotEmpty() | 若陣列為空或不為空則傳回 true |
contains() | 若陣列包含該元素則傳回 true |
在 API 參考中進一步了解陣列屬性和函式。
本節介紹了一些最常用的操作。
存取與修改元素
要存取和修改陣列中的元素,請使用索引存取運算子 ([]):
fun main() {
val simpleArray = arrayOf(1, 2, 3)
val twoDArray = Array(2) { Array<Int>(2) { 0 } }
// 存取元素並修改它
simpleArray[0] = 10
twoDArray[0][0] = 2
// 列印修改後的元素
println(simpleArray[0])
// 10
println(twoDArray[0][0])
// 2
}如果您嘗試存取超出陣列邊界的索引,Kotlin 會在執行時拋出
ArrayIndexOutOfBoundsException。
您還可以使用 fill(element, fromIndex, toIndex) 函式來就地替換指定範圍內的元素。fromIndex 是包含的 (inclusive),而 toIndex 是不包含的 (exclusive):
fun main() {
val arr = IntArray(3)
println(arr.joinToString())
// 0, 0, 0
arr.fill(1)
println(arr.joinToString())
// 1, 1, 1
arr.fill(0, 0, 2)
println(arr.joinToString())
// 0, 0, 1
}在 Kotlin 中,陣列是不變的 (invariant)。這意味著 Array<String> 不是 Array<Any> 的子型別。這可以防止可能的執行時型別失敗。要表達協變性 (covariance),請使用 Array<out Any> 型別投影:
fun main() {
fun printArr(arr: Array<out Any>) {
for (item in arr) print("$item, ")
}
printArr(arrayOf("k", "t", "n"))
// k, t, n,
}新增與移除元素
由於陣列的大小是固定的,因此它們不支援 .add() 和 .remove() 函式。要執行這些操作,您需要建立一個新陣列。為此,您可以使用以下選項之一:
使用
.copyOf函式:kotlinfun main() { var arr = intArrayOf(0, 1, 2) arr = arr.copyOf(arr.size + 1) println(arr.joinToString()) // 0, 1, 2, 0 arr[arr.lastIndex] = 3 println(arr.joinToString()) // 0, 1, 2, 3 }使用
+或+=運算子:kotlinfun main() { var arr = intArrayOf(0, 1, 2) arr += 3 println(arr.joinToString()) // 0, 1, 2, 3 arr = arr + intArrayOf(4, 5) println(arr.joinToString()) // 0, 1, 2, 3, 4, 5 }
如果您需要頻繁地新增或移除元素,請改用可變集合。
比較陣列
要比較兩個陣列是否具有相同順序的相同元素,請使用 .contentEquals() 和 .contentDeepEquals() 函式:
fun main() {
val simpleArray = arrayOf(1, 2, 3)
val anotherArray = arrayOf(1, 2, 3)
// 比較陣列內容
println(simpleArray.contentEquals(anotherArray))
// true
// 使用中綴標記法,在元素更改後比較陣列內容
simpleArray[0] = 10
println(simpleArray contentEquals anotherArray)
// false
}請勿使用相等 (
==) 和不等 (!=) 運算子來比較陣列的內容。這些運算子會檢查指派的變數是否指向同一個物件。若要進一步了解為何 Kotlin 中的陣列會這樣運作,請參閱我們的部落格文章。
轉換陣列
Kotlin 有許多用於轉換陣列的實用函式。本節重點介紹其中一些。 如需完整清單,請參閱我們的 API 參考。
加總
要傳回陣列中所有元素的總和,請使用 .sum() 函式:
fun main() {
val sumArray = arrayOf(1, 2, 3)
println(sumArray.sum())
// 6
}
.sum()函式只能用於數值資料型別的陣列,例如Int。
排序與打亂
您可以使用 .sort() 函式按自然順序對陣列中的元素進行排序,或者使用 .shuffle() 函式隨機打亂它們:
fun main() {
val simpleArray = arrayOf(1, 2, 3)
// 隨機打亂元素
simpleArray.shuffle()
println(simpleArray.joinToString())
// 排序元素
simpleArray.sort()
println(simpleArray.joinToString())
// 1, 2, 3
}要獲取新的排序後陣列而不修改原始陣列,請改用 .sortedArray() 函式。
將可變數量的引數傳遞給函式
在 Kotlin 中,您可以透過 vararg 參數向函式傳遞可變數量的引數。這在您預先不知道引數數量時非常有用,例如在格式化訊息或建立 SQL 查詢時。
要將包含可變數量引數的陣列傳遞給函式,請使用展開運算子 (*)。展開運算子會將陣列的每個元素作為個別引數傳遞給您選擇的函式:
fun main() {
val lettersArray = arrayOf("c", "d")
printAllStrings("a", "b", *lettersArray)
// abcd
}
fun printAllStrings(vararg strings: String) {
for (string in strings) {
print(string)
}
}如需更多資訊,請參閱可變參數 (varargs)。
轉換為集合
如果您使用的不同 API 中,有些使用陣列而有些使用集合,則可以將陣列轉換為集合,反之亦然。為此,請使用 .toList()、.toSet() 和 .toMap() 函式。 這些函式會將陣列內容複製到獨立的複本中。它們不會反映對陣列的後續更改。
轉換為 List 或 Set
要將陣列轉換為 List 或 Set,請使用 .toList() 和 .toSet() 函式:
fun main() {
val simpleArray = arrayOf("a", "b", "c", "c")
// 轉換為 Set
println(simpleArray.toSet())
// [a, b, c]
// 轉換為 List
println(simpleArray.toList())
// [a, b, c, c]
}除非您完全確定原始陣列不會在其他地方被更改或共享,否則請勿使用 .asList() 及相關的 as* 函式。這些函式是包裝原始陣列而不是複製它。因此,對陣列的更改會反映在 list 中,反之亦然。
fun main() {
val simpleArray = arrayOf("a", "b", "c")
val list = simpleArray.asList()
simpleArray[0] = "d"
println(list)
// [d, b, c]
}轉換為 Map
要將陣列轉換為 Map,請使用 .toMap() 函式。
您只能將 Pair<K,V> 的陣列轉換為 Map。 Pair 執行個體的第一個值成為鍵 (key),第二個值成為值 (value)。 如果同一個鍵出現多次,則使用最後一個值。
此範例使用中綴標記法來呼叫 .to 函式以建立 Pair 的元組:
fun main() {
val pairArray = arrayOf("apple" to 120, "banana" to 150, "cherry" to 90, "apple" to 140)
// 轉換為 Map
// 水果是鍵,卡路里數是值
// 最後一個 "apple" 的值會覆蓋第一個
println(pairArray.toMap())
// {apple=140, banana=150, cherry=90}
}後續步驟
- 在集合概覽中進一步了解為什麼我們建議在大多數使用案例中使用集合。
- 了解其他基本型別。
- 如果您是 Java 開發人員,請閱讀我們的集合 Java 到 Kotlin 遷移指南。
